在Python中定义类的方法时,它看起来像这样:

class MyClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

但是在其他一些语言中,比如c#,你有一个对象的引用,这个对象是用"this"关键字绑定的,而不是在方法原型中作为参数声明的。

这是Python中有意的语言设计决策,还是有一些实现细节需要传递“self”作为参数?


当前回答

我认为除了“Python之禅”之外,真正的原因是函数是Python中的第一类公民。

这本质上使它们成为对象。最基本的问题是如果你的函数也是对象那么在面向对象的范例中当消息本身是对象时你将如何向对象发送消息?

看起来像一个先有鸡还是先有蛋的问题,为了减少这种矛盾,唯一可能的方法是将执行上下文传递给方法或检测它。但是由于python可以有嵌套函数,因此不可能这样做,因为内部函数的执行上下文会发生变化。

这意味着唯一可能的解决方案是显式传递'self'(执行上下文)。

所以我认为这是一个执行问题,禅宗来得晚了很多。

其他回答

Python不会强制你使用"self"。你可以给它起任何你想要的名字。你只需要记住方法定义头中的第一个参数是对对象的引用。

还有另一个非常简单的答案:根据python的禅宗,“显式比隐式好”。

我认为除了“Python之禅”之外,真正的原因是函数是Python中的第一类公民。

这本质上使它们成为对象。最基本的问题是如果你的函数也是对象那么在面向对象的范例中当消息本身是对象时你将如何向对象发送消息?

看起来像一个先有鸡还是先有蛋的问题,为了减少这种矛盾,唯一可能的方法是将执行上下文传递给方法或检测它。但是由于python可以有嵌套函数,因此不可能这样做,因为内部函数的执行上下文会发生变化。

这意味着唯一可能的解决方案是显式传递'self'(执行上下文)。

所以我认为这是一个执行问题,禅宗来得晚了很多。

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

也允许你这样做:(简而言之,调用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。像这样的魔术允许框架做一些事情,否则会非常冗长。

再说一次,我不想评论这些东西的道德性。我只是想展示一些如果没有显式的自我引用就很难做到的事情。