Python中的类属性和实例属性以及静态方法和类方法

能够在Python的类定义中直接添加静态变量,以下例中的foo。此属性属于类C,能够直接经过C.foo访问,而无需实例化它。而实例属性则只存在于对象的实例中,这也就意味着,每个不一样的实例都有只属于本身的实例属性。 python

class C:
    def __init__(self):
        pass
    foo = 'foo'
c = C()

当咱们试图经过一个实例访问某个属性的时候,解释器会首先尝试在实例的命名空间里寻找,若是找不到就会去类属性里找。所以,便会出现下面的状况: 函数

>>> C.foo 
'foo' 
>>> c.foo 
'foo' 
>>> C.foo = 'bar' 
>>> C.foo 
'bar' 
>>> c.foo 
'bar' 
>>> c.foo = 'instance' 
>>> c.foo 
'instance' 
>>> C.foo 
'bar'

当咱们实例化C类并将此实例赋值给c时,经过类C和实例c均可以访问到foo属性,实际上这时候访问的是同一个“类属性”(此属性不存在于实例c的命名空间中)。这一点从下面,咱们经过类C改变foo的值后,经过实例c访问foo的值也变了,能够看得出来。而当咱们试图经过实例c给foo赋值的时候,解释器会把c.foo = 'instance' 这条命令理解为“给实例c的foo属性赋值”,而当他发现实例c没有foo属性的时候,便会自动的给实例c建立一个。这个时候再经过实例c去访问类C的类属性foo就是行不通的了。 ui

经过上面的例子能够看到,类属性的本体是属于类自身的,而实例仅在没有本身的同名实例属性时才能够访问到他。这种特质的一个应用方式就是标记类自身的某些属性,好比版本信息。 code

P.S.类定义的方法全都是类属性,在实例被建立以前这些方法都不能被调用,由于他们尚未被绑定到特定的实例上。或者也能够简单的理解为,缺乏能够传递给类方法的self参数于是调用失败。(arguments 0 given 1 required)除非:使用staticmethod()或classmethod()内建函数将类定义的某个方法“标记(tag),强制类型转换(cast)或者转换(convert)”为静态方法或者类方法。例如以下定义C类: orm

class C:
   def __init__(self):
       pass

   def foo():
       print("calling static method foo().")
   foo = staticmethod(foo)

   def bar(cls):
       print("calling class method bar().")
       print("bar() is part of class:",cls.__name__)
   bar = classmethod(bar)

当调用foo()和bar()方法时,就不用再实例化C了。注意类方法bar()在定义时传入的默认参数cls,它的做用与self相似(一样只是一个约定俗成的名字cls用于指代类自己): 对象

>>> C.foo() 
calling static method foo(). 
>>> C.bar() 
calling class method bar(). 
bar() is part of class: C

关于Python的类定义方法时为啥必须显式传递一个self参数的问题,这用来表示该方法是不是绑定的,以及绑定在了何处(self / cls)。 ci

相关文章
相关标签/搜索