Python - self, 无 self 和 cls

84 投票
2 回答
89244 浏览
提问于 2025-04-17 03:05

又一个关于'self'是什么、如果不使用'self'会发生什么,以及'cls'是什么的问题。我“已经做了功课”,只是想确认我理解得是否正确。

self - 要访问一个对象的属性,你需要在属性名前加上对象的名字(objname.attributename)。同样,self就是用来在对象(类)内部访问属性的。如果在类的方法中没有用self前缀一个变量,你就无法在这个类的其他方法中或者类外部访问这个变量。所以,如果你只想让这个变量在某个方法内部使用,可以不加self。如果你有一个方法,并且不需要与其他方法共享任何变量,也可以不把self放在方法的参数里。

cls - 每个实例都会创建自己属性的“副本”,所以如果你想让一个类的所有实例共享同一个变量,你需要在类声明中用cls前缀这个变量名。

这样理解对吗?谢谢。

2 个回答

18

在普通的方法中,你会用 self 作为第一个参数,这样实例就会通过这个参数自动传递过来。也就是说,方法里的第一个参数指向的是当前的实例

当一个方法加上 @classmethod 装饰器时,它的第一个参数会传入类,所以通常会把这个参数命名为 cls,因为它指向的是

通常你不需要在变量名前加前缀(匈牙利命名法是不好的做法)。


下面是一个例子:

class Test(object):
    def hello(self):
        print 'instance %r says hello' % self
    @classmethod
    def greet(cls):
        print 'class %r greet you' % cls

输出结果:

>>> Test().hello()
instance <__main__.Test object at 0x1f19650> says hello

>>> Test.greet()
class <class '__main__.Test'> greet you
125

self就像是用来访问对象(类)内部的属性。

其实不是在对象/类内部,而是在类的实例方法内部。self只是一个约定,你可以把它叫成其他任何名字,甚至在每个方法里都用不同的名字。

所以如果你在类的方法里没有用self前缀一个变量,你就不能在类的其他方法里或者类外访问这个变量。

self是在实例方法中使用的,而cls通常是在类方法中使用的。其他的说法都是对的。

所以如果你只想让变量在那个方法内部使用,可以不加self。

没错,在一个方法里,变量名就像在其他任何函数里一样——解释器会先在本地查找这个名字,然后在闭包中查找,再然后在全局/模块级别查找,最后在Python内置函数中查找。

同样,如果你有一个方法,并且不想和其他方法共享任何变量,你可以不在方法参数中加self。

不行,你不能直接省略方法参数中的"self"。你必须告诉Python你想要一个staticmethod,这样它就不会自动传递类的实例,可以通过在def行上方加@staticmethod,或者在方法体下面用mymethod = staticmethod(mymethod)来实现。

每个实例都会创建自己的属性“副本”,所以如果你想让一个类的所有实例共享同一个变量,你需要在类声明中用'cls'前缀这个变量名。

类定义内部,但在任何方法外部,名字是绑定到类上的——这就是你定义方法等的方式。你不需要在它们前面加cls或其他任何东西。

cls通常在__new__这个特殊的staticmethod中使用,或者在classmethod中使用,创建方式和staticmethod类似。这些方法只需要访问类,而不需要访问每个实例特有的东西。

classmethod内部,是的,你会用这个来指代你希望所有类的实例和类本身共享的属性。

self一样,cls也只是一个约定,你可以把它叫成任何你想要的名字。

简单的例子:

class Foo(object):

    # you couldn't use self. or cls. out here, they wouldn't mean anything

    # this is a class attribute
    thing = 'athing'

    def __init__(self, bar):
        # I want other methods called on this instance of Foo
        # to have access to bar, so I create an attribute of self
        # pointing to it
        self.bar = bar

    @staticmethod
    def default_foo():
        # static methods are often used as alternate constructors,
        # since they don't need access to any part of the class
        # if the method doesn't have anything at all to do with the class
        # just use a module level function
        return Foo('baz')

    @classmethod
    def two_things(cls):
        # can access class attributes, like thing
        # but not instance attributes, like bar
        print cls.thing, cls.thing

撰写回答