在Python中定义类的方法时,它看起来像这样:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
但是在其他一些语言中,比如c#,你有一个对象的引用,这个对象是用"this"关键字绑定的,而不是在方法原型中作为参数声明的。
这是Python中有意的语言设计决策,还是有一些实现细节需要传递“self”作为参数?
在Python中定义类的方法时,它看起来像这样:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
但是在其他一些语言中,比如c#,你有一个对象的引用,这个对象是用"this"关键字绑定的,而不是在方法原型中作为参数声明的。
这是Python中有意的语言设计决策,还是有一些实现细节需要传递“self”作为参数?
当前回答
也允许你这样做:(简而言之,调用Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5)将返回12,但将以最疯狂的方式这样做。
class Outer(object):
def __init__(self, outer_num):
self.outer_num = outer_num
def create_inner_class(outer_self, inner_arg):
class Inner(object):
inner_arg = inner_arg
def weird_sum_with_closure_scope(inner_self, num)
return num + outer_self.outer_num + inner_arg
return Inner
当然,这在Java和c#等语言中很难想象。通过使自引用显式,您可以自由地通过该自引用引用任何对象。而且,这种在运行时处理类的方式在静态语言中更难做到——这并不是说它一定是好是坏。只是外显的自我允许所有这些疯狂的存在。
此外,想象一下:我们想要定制方法的行为(用于分析,或一些疯狂的黑魔法)。这可能会导致我们思考:如果我们有一个类Method,我们可以重写或控制它的行为呢?
就是这样:
from functools import partial
class MagicMethod(object):
"""Does black magic when called"""
def __get__(self, obj, obj_type):
# This binds the <other> class instance to the <innocent_self> parameter
# of the method MagicMethod.invoke
return partial(self.invoke, obj)
def invoke(magic_self, innocent_self, *args, **kwargs):
# do black magic here
...
print magic_self, innocent_self, args, kwargs
class InnocentClass(object):
magic_method = MagicMethod()
现在:InnocentClass().magic_method()将像预期的那样工作。该方法将与innocent_self参数绑定到InnocentClass,与magic_self绑定到MagicMethod实例。奇怪的是吧?这就像在Java和c#等语言中有两个关键字this1和this2。像这样的魔术允许框架做一些事情,否则会非常冗长。
再说一次,我不想评论这些东西的道德性。我只是想展示一些如果没有显式的自我引用就很难做到的事情。
其他回答
还有另一个非常简单的答案:根据python的禅宗,“显式比隐式好”。
我建议大家应该读读Guido van Rossum关于这个话题的博客——为什么外显的自我必须留下来。
When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '@classmethod' or '@staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not. I reject hacks like special-casing '@classmethod' and '@staticmethod'.
我认为这和PEP 227有关
Names in class scope are not accessible. Names are resolved in the innermost enclosing function scope. If a class definition occurs in a chain of nested scopes, the resolution process skips class definitions. This rule prevents odd interactions between class attributes and local variable access. If a name binding operation occurs in a class definition, it creates an attribute on the resulting class object. To access this variable in a method, or in a function nested within a method, an attribute reference must be used, either via self or via the class name.
我喜欢引用彼得斯的《Python禅》。“明确的比含蓄的好。”
在Java和c++中,'this。'可以被推导出来,除非你的变量名使它无法推导。所以你有时需要它,有时不需要。
Python选择显式地做这样的事情,而不是基于规则。
此外,由于没有隐含或假设任何内容,部分实现将被公开。自我。__class__进行自我。__dict__和其他“内部”结构可以以一种明显的方式使用。
self形参保存当前调用对象。
class class_name:
class_variable
def method_name(self,arg):
self.var=arg
obj=class_name()
obj.method_name()
在这里,self参数保存对象obj。因此,语句self。Var表示obj.var