静态属性的陷阱 python中类与对象的命名空间、__dict__ 和 dir 在继承中使用说明( 三 )


对类中静态属性访问规则:(1)对于不可变数据类型来说,最好用类名操作静态属性;    若用对象名操作静态属性,其修改 和 重新赋值 都是独立的(独立的:对象与类的命名空间分开存放)    1)若用对象名第一次修改静态属性,首先会到类的命名空间中找到该静态属性的属性值,然后在当前对象的命名空间中再做修改        2)若用对象名直接给静态属性重新赋值,那么直接会在当前对象的命名空间中添加这一属性(2)对于可变数据类型来说,用对象名修改是 共享的,用对象名重新赋值是 独立的    因为修改的是指针变量所指向内存中的值,故是 共享的!!!总结,操作静态属性,最好用类名操作静态属性;
补充:python中不可变数据类型与可变数据类型【静态属性的陷阱 python中类与对象的命名空间、__dict__ 和 dir 在继承中使用说明】不可变数据类型:对于相同的值对应的内存地址是不变的;
 1 a = 1 2 b = 1 3 c = 2 4 d = a + b 5 print(" id(a) = %d\n id(b) = %d\n id(c) = %d\n id(d) = %d\n" 6       % (id(a), id(b), id(c), id(d))) 7 8 """ 9  id(a) = 146156361610  id(b) = 146156361611  id(c) = 146156364812  id(d) = 146156364813 """可变的数据类型:对于相同值的内存地址是可变的;
 1 al = [1, 2, 3] 2 bl = [1, 2, 3] 3 print(" id(al) = %d\n id(bl) = %d\n" % (id(al), id(bl))) 4 al.append(4) 5 bl += [4] 6 print(" id(al) = %d\n id(bl) = %d\n" % (id(al), id(bl))) 7 print(" al:%s\n bl:%s\n" % (al, bl)) 8 9 """10  id(al) = 235396500372011  id(bl) = 23539647358161213  id(al) = 235396500372014  id(bl) = 23539647358161516  al:[1, 2, 3, 4]17  bl:[1, 2, 3, 4]18 """类属性的补充一:我们定义的类的属性到底存到哪里了?有两种方式查看dir(类名):查出的是一个名字列表类名.__dict__:查出的是一个字典,key为属性名,value为属性值二:特殊的类属性类名.__name__   # 类的名字(字符串)类名.__doc__    # 类的文档字符串类名.__base__   # 类的第一个父类类名.__bases__  # 类所有父类构成的元组类名.__dict__   # 类的字典属性类名.__module__ # 类定义所在的模块类名.__class__  # 实例对应的类(仅新式类中)3 __dict__ 与 dir() 的使用"""对象名.__dict__:查看对象的属性(self对象中存储的变量)类名.__dict__:查看类的属性(在类中能看到的静态属性与动态属性)dir(对象名):查看对象的所有属性(此时包括self对象、类属性、内置方法)dir(类名):查看类的所有属性(不包括self对象)注:在继承中,子类名.__dict__中看不到父类中的类属性,但实际上包括父类的类属性"""案例分析
class Family:    '''    定义一个公共账号 ,只要有人上班,就将钱存到这个账号上    '''    share_money = 0  # 不可变数据类型做静态属性    native_place = ['china']    # 可变数据类型做静态属性    def __init__(self, role, name, salary):        self.role = role        self.name = name        self.salary = salary    def work(self):        Family.share_money += self.salary   # 将每个人的钱都存放到这个公共账号上        print('the account remains ¥%s '%Family.share_money)    def fun(self):        passclass NewFamily(Family):    new_account = 0    def __init__(self, role, name, salary, kind):        super(NewFamily, self).__init__(role, name, salary)        self.kind = kind    def work(self):        pass    # 使用__定义私有属性    # python中不存在严格的私有属性,在类的外部可通过正真的函数名【_类名__函数名,即 _NewFamily__expenditure】间接调用    def __expenditure(self):        passf = Family('father', 'lilei', 1000)nf = NewFamily("son", "liwei", 2000, "salesman")print("-"*20, "nf.__dict__ 与 f.__dict__ 对比", "-"*20)print(f.__dict__)print(nf.__dict__)print(set(nf.__dict__) - set(f.__dict__))print("-"*20, "NewFamily.__dict__ 与 Family.__dict__ 对比", "-"*20)print(Family.__dict__)print(NewFamily.__dict__)print(set(NewFamily.__dict__) - set(Family.__dict__))print("-"*20, "dir(nf) 与 dir(f) 对比", "-"*20)print(dir(f))print(dir(nf))print(set(dir(nf)) - set(dir(f)))print("-"*20, "dir(NewFamily) 与 dir(Family) 对比", "-"*20)print(dir(Family))print(dir(NewFamily))print(set(dir(NewFamily)) - set(dir(Family)))

经验总结扩展阅读