p149-
#封装:把属性和方法装起来
#广义:把属性和方法装起来,外面不能直接调用了,要通过类的名字调用
#狭义:把属性和方法藏起来,外面不能调用,只能内部调用,在定义属性前面加个双下划线(如:__pwd)
class User:
__Country = 'China' #私有静态变量
def __init__(self,name,password):
self.name = name
self.__pwd = password #私有实例变量
u1=User('tom','123456')
print(u1.__pwd) #AttributeError: 'User' object has no attribute '__pwd' #报错
#给一个变量前面加上双下划线的时候,这个名字变成私有
#所有的私有的内容或者名字都不能再类的外面调用,只能在类的内部使用
# #获取私有实例变量可以通过,类方法
class User:
__Country = 'China' #私有静态变量
def __init__(self,name,password):
self.name = name
self.__pwd = password #私有实例变量
def get_pwd(self):
return self.__pwd
u1=User('tom','123456')
print(u1.get_pwd()) #123456
# #如果非要改私有实力变量呢,也通过类的方法
class User:
__Country = 'China' #私有静态变量
def __init__(self,name,password):
self.name = name
self.__pwd = password #私有实例变量
def get_pwd(self):
return self.__pwd
def change_pwd(self,new_pwd):
self.__pwd = new_pwd
u1=User('tom','123456')
u1.change_pwd('111111')
print(u1.get_pwd())
#如果只返回加密后的密码 pwd
import hashlib
class User:
__Country = 'China' #私有静态变量
def __init__(self,name,password):
self.name = name
self.__pwd = password #私有实例变量
def get_pwd(self):
ret = hashlib.md5() #这里还可以用User的name加盐 ret = hashlib.md5(self.name.encode('utf-8'))
# ret = hashlib.md5(self.name.encode('utf-8'))
ret.update(self.__pwd.encode('utf-8'))
return ret.hexdigest()
u1=User('tom','123456')
print(u1.get_pwd()) #e10adc3949ba59abbe56e057f20f883e
print(u1.get_pwd()) #f19b50d5e3433e65e6879d0e66632664 #加盐后的结果
#还可以做私有的方法,把加密的步骤写成私有的方法
import hashlib
class User:
__Country = 'China' #私有静态变量
def __init__(self,name,password):
self.name = name
self.__pwd = password #私有实例变量
def __md5_pwd(self): #把方法私有化
ret = hashlib.md5() # 这里还可以用User的name加盐 ret = hashlib.md5(self.name.encode('utf-8'))
# ret = hashlib.md5(self.name.encode('utf-8'))
ret.update(self.__pwd.encode('utf-8'))
return ret.hexdigest()
def get_pwd(self):
return self.__md5_pwd()
u1=User('tom','123456')
print(u1.get_pwd()) #e10adc3949ba59abbe56e057f20f883e
# print(u1.__md5_pwd()) #报错
#所有写在类里的都可以私有化
#私有变量为啥不能被外部调用?
class User:
__Country = 'China'
__hobby = 'Football' #在类的外部不能定义私有的概念
def func(self):
print(self.__Country) #在类的内部,自动把当前这句话所在的类名字拼接在私有变量,来完成变形
print(User._User__Country) #China
print(User._User__hobby) #Football
#私有内容能不能被子类使用? 不能
class Foo(object):
def __init__(self):
self.func()
def func(self):
print('in Foo')
class Son(Foo):
def func(self):
print('in son')
Son() #in son 实例化的时候 init 找父类 Foo ,然后init里面的func 是self调用的,就先从子类中找
class Foo(object):
def __init__(self):
self.__func() ##在类的内部,自动把当前这句话所在的类名字拼接在私有变量,来完成变形,这里self 虽然是Son实例化的对象
##但是 在类的内部,自动把当前这句话所在的类名字拼接在私有变量上,来完成变形,__func变成_Foo__func
def __func(self):
print('in Foo')
class Son(Foo):
def __func(self):
print('in son')
Son() #in Foo
class Foo(object):
def __func(self):
print('in Foo')
class Son(Foo):
def __init__(self):
self.__func() #self调用__func()的时候是调用了 _Son__func ,但是子类中没有
Son() # 报错 AttributeError: 'Son' object has no attribute '_Son__func'
#在其他语言中的数据级别都有哪些?在python中有哪些
#public 公有的 类内类外都能用,父类子类都能用
#protect 保护的 类内能用,类外不行,父类子类都能用 python 不支持保护的
#private 私有的 本类的类内能用,其他地方不能用
#类的装饰器 property
#property
from math import pi
class Circle:
def __init__(self,r):
self.r = r
@property #添加property装饰器,结尾就可以直接调用area方法 作为属性 把一个方法伪装成属性,调用的时候就不用加括号了
def area(self):
return self.r**2*pi
c1 = Circle(10)
print(c1.area) #314.1592653589793
#被装饰的方法不能有参数
import time
class Person:
def __init__(self,name,birth):
self.name = name
self.birth = birth
@property
def age(self): #方法伪装成属性 ,另外这个方法不能有参数
return time.localtime().tm_year-self.birth
p1 = Person('tom',1998)
print(p1.age) #22
#property的应用场景 : 和私有属性合作
class User:
def __init__(self,name,pwd):
self.name = name
self.__pwd = pwd #把密码设置成私有变量,在下面伪装一个pwd方法为属性,就实现了,只能看,不能改的场景
@property
def pwd(self):
return self.__pwd
u1 = User('tom','123456')
print(u1.pwd)
u1.pwd = 12111 #AttributeError: can't set attribute 不能改
#如果就想改变伪装的变量的私有属性
class Goods: #商品类
def __init__(self,name,price):
self.name = name
self.__price = price
@property
def price(self):
return self.__price
@price.setter #增加一个装饰器,结构为‘@被装饰函数名.setter’
def price(self,new_price):
self.__price = new_price
g1 = Goods('pen',5)
print(g1.price) #5
g1.price = 10
print(g1.price) #10
#这跟设置一个公共属性有什么区别,这里可以防止给属性非法赋值,比如 g1.price = ‘aaa’
#变更一下
class Goods: #商品类
def __init__(self,name,price):
self.name = name
self.__price = price
@property
def price(self):
return self.__price
@price.setter #增加一个装饰器,结构为‘@被装饰函数名.setter’
def price(self,new_price):
if isinstance(new_price,int): #判断只有整数时才能赋值,否则没变化
self.__price = new_price
g1 = Goods('pen',5)
print(g1.price) #5
g1.price = 'aa' #不生效
print(g1.price) #5