[Python]面向对象编程---类、实例、方法的对比(4)

来源:互联网 发布:php self this区别 编辑:程序博客网 时间:2024/05/17 21:40

一、类属性 vs 实例属性

1、访问类属性

>>> class C(object):        # 定义类        version = 1.2       # 静态成员

(1) 当用实例来访问类属性时,Python会先在实例中搜索名字version,然后是类,再就是继承树中的基类。
(2) 通过类才能更新它的值
>>> c = C()                 # 实例化>>> C.version               # 通过类来访问1.2>>> c.version               # 通过实例来访问1.2>>> C.version += 0.1        # 通过类来更新(只能这样)>>> C.version               # 类访问1.3>>> c.version               # 实例访问它,其值已被改变1.3

2、通过实例访问类的属性

任何对实例属性的赋值都会创建一个实例属性(如果不存在的话),并且对其赋值。

如果类属性中存在同名的属性,会产生副作用
>>> c.version += 0.2       # 尝试更新类属性  等价于 c.version = C.version + 0.2>>> c.version              # 只是创建了一个新的实例属性1.5>>> C.version              # 没有更新类属性,只是创建了一个新的实例属性1.3>>> del c.version          # 删除实例属性>>> c.version              # 又可以访问到类属性1.3>>> C.version1.3
3、在类属性可变的情况下,通过实例可以更新类属性

>>> class Foo(object):...     x = {2003: 'yes'}   # 字典类型,可以修改
>>> foo = Foo()             # 实例化 >>> foo.x{2003: 'yes'}>>> foo.x[2004] = 'no'      # 通过实例修改类属性,生效>>> foo.x{2003: 'yes', 2004: 'no'}>>> Foo.x                   # 修改生效{2003: 'yes', 2004: 'no'}>>> del foo.x               # 没有遮蔽所以不能删除掉Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: x 
二、绑定和方法调用

1、方法

(1) 方法仅仅是类内部定义的函数(是类属性,不是实例属性)

(2) 方法只有在其所属的类拥有实例时,才能被调用

(3) 任何一个方法定义中的第一个参数都是变量self,它表示调用此方法的实例对象。

2、调用绑定方法

MyClass类和实例mc,想要调用MyClass中的方法foo,只需调用mc.foo()即可。

3、调用非绑定方法

当没有实例并且需要调用一个非绑定方法时,必须传递self参数

def __init__(self, nm, ph, id, em):                  AddrBookEntry.__init__(self, nm, ph)    # 通过父类名来调用        self.empid = id        self.email = em
三、静态方法 vs 类成员方法

静态方法可以被类或实例访问不能访问类变量,不能访问实例变量。

类成员方法可以被类或实例访问,可以访问类变量,不能访问实例变量。

class MyClass(object):    val1 = 'abcd'             # 类属性    def __init__(self):        self.val2 = 'a1b2c3'  # 实例属性    @staticmethod             # 使用装饰器定义静态方法    def staticMd():        print("static method, can't access val1 and val2")    @classmethod              # 使用装饰器定义类成员方法    def classMd(cls):        print("class method, class: %s, val1 = %s, can't access val1" % (str(cls), cls.val1))
>>> mc = MyClass()        # 实例化>>> mc.staticMd()         # 通过实例访问静态方法static method, can't access val1 and val2>>> MyClass.staticMd()    # 通过类访问静态方法static method, can't access val1 and val2>>> mc.classMd()          # 通过实例访问类成员方法class method, class: <class 'MyData.MyClass'>, val1 = abcd, can't access val1>>> MyClass.classMd()     # 通过类访问类成员方法class method, class: <class 'MyData.MyClass'>, val1 = abcd, can't access val1  
>>> mc.val1               # 实例访问类属性'abcd'>>> MyClass.val1          # 类访问类属性'abcd'>>> mc.val2               # 实例访问实例属性'a1b2c3'>>> MyClass.val2          # 类无法访问实例属性Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: type object 'MyClass' has no attribute 'val2'
>>> mc.val1 = "haha"     # 创建了一个实例属性 val1>>> mc.val1              # 访问实例属性 val1'haha'>>> MyClass.val1         # 此时类属性val1并没有改变'abcd'>>> MyClass.val1 = "a1b1c1"  # 通过类更新类属性>>> MyClass.val1         # 类属性已经更新'a1b1c1'>>> mc.val1              # 实例属性val1没有改变'haha'>>> del mc.val1          # 删除实例属性val1>>> mc.val1              # 此时可以通过实例访问类属性'a1b1c1'







0 0
原创粉丝点击