类的进阶(3)
一、私有静态属性,私有方法,私有属性
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属性
示例:
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取到 类,很关键。类加括号实例化对象。
浙公网安备 33010602011771号