我通过关注pygame tutorials来学习Python。
其中我发现广泛使用关键字 self ,并且来自主要的Java背景,我发现我一直忘记输入 self 。例如,我会输入self.rect.centerx
而不是rect.centerx
,因为对我来说, rect 已经是该类的成员变量。
我可以想到的Java并行是这种情况,必须使用 this 为所有对成员变量的引用添加前缀。
我是否使用 self 为所有成员变量添加前缀,或者是否有办法声明它们以避免必须这样做?
即使我建议的不是 pythonic ,我仍然想知道是否可能。
我已经看过这些相关的SO问题,但他们并没有完全回答我的想法:
答案 0 :(得分:85)
Python需要指定self。结果是,即使没有可见的完整类定义,也不会对成员和不成员的内容产生任何混淆。这会导致有用的属性,例如:您无法添加意外隐藏非成员的成员,从而破坏代码。
一个极端的例子:你可以在不知道它可能具有什么基类的情况下编写一个类,并且总是知道你是否正在访问一个成员:
class A(some_function()):
def f(self):
self.member = 42
self.method()
那是完整的代码! (some_function返回用作基础的类型。)
另一个,类的方法是动态组合的:
class B(object):
pass
print B()
# <__main__.B object at 0xb7e4082c>
def B_init(self):
self.answer = 42
def B_str(self):
return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?
B.__init__ = B_init
B.__str__ = B_str
print B()
# <The answer is 42.>
请记住,这两个例子都是极端的,你不会每天都看到它们,我也不建议你经常写这样的代码,但是它们确实清楚地显示了自我明确需要的方面。
答案 1 :(得分:23)
实际上self
不是关键字,它只是传统上给Python中实例方法的第一个参数赋予的名称。并且不能跳过第一个参数,因为它是方法知道调用哪个类实例的唯一机制。
答案 2 :(得分:21)
您可以使用您想要的任何名称,例如
class test(object):
def function(this, variable):
this.variable = variable
甚至
class test(object):
def function(s, variable):
s.variable = variable
但你仍然坚持使用范围的名称。
除非你有一个令人信服的理由,否则我不建议你使用与自我不同的东西,因为它会使有经验的pythonistas变得陌生。
答案 3 :(得分:16)
以前的答案基本上都是&#34;你可以&#34;#34;或者&#34;你不应该&#34;。虽然我同意后一种观点,但问题在技术上仍然没有答案。
此外,有正当理由可以解释为什么某人可能想要按照实际问题的要求做某事。有时我遇到的一件事是冗长的数学方程,其中使用长名称使方程变得无法识别。以下是一些如何在固定示例中执行此操作的方法:
import numpy as np
class MyFunkyGaussian() :
def __init__(self, A, x0, w, s, y0) :
self.A = float(A)
self.x0 = x0
self.w = w
self.y0 = y0
self.s = s
# The correct way, but subjectively less readable to some (like me)
def calc1(self, x) :
return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
* np.exp( -(x-self.x0)**2/self.w**2)
* (1+self.s*(x-self.x0)**2) + self.y0 )
# The correct way if you really don't want to use 'self' in the calculations
def calc2(self, x) :
# Explicity copy variables
A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
# Probably a bad idea...
def calc3(self, x) :
# Automatically copy every class vairable
for k in self.__dict__ : exec(k+'= self.'+k)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))
第三个例子 - 即使用for k in self.__dict__ : exec(k+'= self.'+k)
基本上是问题的实际要求,但让我明确一点,我认为这通常不是一个好主意。
有关更多信息以及迭代类变量甚至函数的方法,请参阅this question的答案和讨论。有关动态命名变量的其他方法的讨论,以及为什么这通常不是一个好主意,请参阅this blog post。
答案 4 :(得分:9)
是的,你必须始终指定self
,因为根据python哲学,explicit比隐式更好。
你还会发现你在python中编程的方式与你在java中编程的方式有很大不同,因此self
的使用趋于减少,因为你没有在对象内部投射所有东西。相反,您可以更多地使用模块级功能,这可以更好地进行测试。
答案 5 :(得分:5)
self是访问对象成员的python语法的一部分,所以我担心你会被它困住
答案 6 :(得分:5)
“self”是类的当前对象实例的传统占位符。当你想在类中引用对象的属性或字段或方法时使用它,就好像你指的是“它自己”一样。但是为了缩短Python编程领域的某些人开始使用“自我”,其他领域使用“this”但他们将其作为一个无法替换的关键字。我宁愿用“它”来增加代码的可读性。它是Python中的好东西之一 - 您可以自由地为对象的实例选择自己的占位符而不是“self”。 自我的例子:
class UserAccount():
def __init__(self, user_type, username, password):
self.user_type = user_type
self.username = username
self.password = encrypt(password)
def get_password(self):
return decrypt(self.password)
def set_password(self, password):
self.password = encrypt(password)
现在我们将'self'替换为'its':
class UserAccount():
def __init__(its, user_type, username, password):
its.user_type = user_type
its.username = username
its.password = encrypt(password)
def get_password(its):
return decrypt(its.password)
def set_password(its, password):
its.password = encrypt(password)
现在更具可读性?
答案 7 :(得分:1)
是的,自我是乏味的。但是,它更好吗?
class Test:
def __init__(_):
_.test = 'test'
def run(_):
print _.test
答案 8 :(得分:1)
实际上你可以使用食谱&#34;隐含的自我&#34;来自Armin Ronacher的演讲&#34; 5年的糟糕想法&#34; (google it)。
这是一个非常聪明的食谱,几乎所有来自Armin Ronacher,但我不认为这个想法非常吸引人。我想我更喜欢C#/ Java中明确的 this 。
更新。链接到&#34;坏主意食谱&#34;:https://speakerdeck.com/mitsuhiko/5-years-of-bad-ideas?slide=58
答案 9 :(得分:0)
From: Self Hell - More stateful functions.
...a hybrid approach works best. All of your class methods that actually do computation should be moved into closures, and extensions to clean up syntax should be kept in classes. Stuff the closures into classes, treating the class much like a namespace. The closures are essentially static functions, and so do not require selfs*, even in the class...
答案 10 :(得分:0)
我认为,如果有一个“成员”语句和“全局”语句,那将更容易且更具可读性,因此您可以告诉解释器哪些是类的对象成员。