一 私有静态属性,私有方法,私有属性
class A: __role='英文单词' def __init__(self,name): self.__name=name def __a(self): pass def b(self): pass print(A.__dict__) A.__role='汉语拼音' print(A.__dict__)
输出:
{'__module__': '__main__', '_A__role': '英文单词', '__init__': <function A.__init__ at 0x0000020A01DB9BF8>, '_A__a': <function A.__a at 0x0000020A01DB9F28>, 'b': <function A.b at 0x0000020A01DD6048>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} {'__module__': '__main__', '_A__role': '英文单词', '__init__': <function A.__init__ at 0x0000020A01DB9BF8>, '_A__a': <function A.__a at 0x0000020A01DB9F28>, 'b': <function A.b at 0x0000020A01DD6048>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, '__role': '汉语拼音'}
私有是在定义阶段变量名前加上__。查看__dict__,会发现实际存储的是 _类名__属性名。
调用阶段__变量名,就没有你什么事了,该咋地咋地。
PS 私有方法的用处:
1 有一些方法的返回值只是用来作为中间结果
2 父类的方法不希望子类继承,子类没法继承父类的__属性。
实例:
class People: def __init__(self,name,pwd): self.name=name self.__pwd=pwd def __hashpwd(self): #返回值作为中间结果 return hash(self.__pwd) def login(self,pwd_info): return hash(pwd_info)==self.__hashpwd() egon=People('egon','123') print(egon.login('1234'))
输出:
False
二 property属性。
@property装饰器是负责把一个方法变为属性调用。
在python中,property( )是一个内置函数,用来创建和返回一property对象 x 。
property对象 x 有三种方法,x.getter(),x.setter(),x.deleter()。
其中x.setter()本身也是装饰器,负责把一个setter方法变成属性赋值。
property广泛应用在类的定义中,可以让定义者写出剪短的代码,同时保证了对参数进行必要的检查,这样程序运行时就减少了出错的可能性。
输出:
class Shop: discount=0.75 def __init__(self,price): self.__price=price @property def price(self): #@property 装饰器将price方法变成Shop对象的一个属性。price变成一个对象,进化了,拥有了setter,deleter方法 return self.__price * Shop.discount @price.setter #@price.setter装饰器, 被装饰的price执行=赋值操作时,执行相关的代码。 def price(self,new_price): self.__price=new_price print('执行setter语句') print('--------------') @price.deleter def bb(self): #被装饰的bb,如果执行del语句,则执行动态属性内的代码 print('执行deleter语句') print('---------------') apple=Shop(1000) print(apple.price) print(apple.__dict__) apple.price=10000 print(apple.price) print(apple.__dict__) del apple.bb apple.p=100000 print(apple.__dict__)
输出:
750.0 {'_Shop__price': 1000} 执行setter语句 -------------- 7500.0 {'_Shop__price': 10000} 执行deleter语句 --------------- {'_Shop__price': 10000, 'p': 100000}
PS:
property函数实现了统一访问原则。统一访问原则就是代码不应由‘属性’ 是通过字段实现还是方法实现而受影响。如果没有property属性,有时候加()调用方法,有实际不加()调用属性。
property实现了都不加( )调,这就叫统一访问原则。
三 封装
封装的原因:
1 保护隐私
2 隔离复杂度
封装原则:
1 把不需要对外显示的数据都隐藏起来
2 把属性隐藏,对外提供公共接口
封装的方法
1 封装数据: 私有属性 __
2 property属性
封装的分类:很重要 !!!
1 把同一类方法封装到类中
class File:增删改查
class DB:增删改查
2 把数据封装到对象中
class File:
def __init__(self,name,age):
self.name = name
self.age = age
....
示例:
class People: def __init__(self,name,age,salary): self.__name=name #数据的封装 self.__age=age self.__salary=salary @property #数据的封装,统一访问原则 def name(self): #属性隐藏,对外部提供接口 return self.__name @name.setter #装饰器 对外提供接口。接口内可以加入逻辑代码 def name(self,x): #执行’改’时,执行下面代码 if not type(x)==str: raise TypeError('请输入字符串!') self.__name = x @name.deleter def name(self): #对外提供接口的时候,可以加入逻辑代码 raise PermissionError('不允许删!') egon=People('egon',35,2500) print(egon.name) egon.name=123 print(egon.name) del egon.name #代码执行会报错,因为上面逻辑设定。
输出:会报错,两个地方有错误。
四 staticmethod 静态方法,classmethod 类方法
staticmethod,不需要使用对象的属性和类的属性。
classmethod,,传一个类的参数,不需要使用对量的属性,只需要使用类的属性。绑定给类。
普通方法:传一个对象的参数,需要使用对象和类的属性,绑定给对象。
class Foo: @classmethod def foo(cls): pass def bar(self): pass f=Foo() print(Foo.foo) print(f.bar)
输出:
都是绑定关系。
<bound method Foo.foo of <class '__main__.Foo'>> <bound method Foo.bar of <__main__.Foo object at 0x0000018420DAEBE0>>
classmethod的应用
import settings class Foo: def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def bar(cls): #绑定给类,把类传进来了。有了这个类,可以定制任意的逻辑,实现了自己想怎么执行就怎么执行 obj=cls(settings.ip,settings.port) #这一步是拿到了类,正常实例化的过程,obj就是Foo的一个对象。拿到了类,想咋地咋地 obj.x=1111111111111111111111 #想咋地咋地 return obj #最根本的是把类传进来,在foo函数内部拿到了这个类
简单来说,可以借用classmethod取到 类,很关键。类加括号实例化对象。