封装
隐藏对象的属性和实现细节,近对外提供公共访问方式
广义:代码保护,面向对象思想
狭义:将属性,方法隐藏起来
class Person: __key = 123456 # 私有的静态属性 def __init__(self,name,passwd): self.name = name self.__passwd = passwd # 私有的属性 def __test(self): # 私有方法 print(self.__dict__) print('私有方法内部调用') ## 只要在类的内部使用私有属性,就会自动带上_类名 def test2(self): return self.__test # 私有方法只能在内部调用 def get_pwd(self): # return self.get_pwd return self.__passwd alex = Person('alex',123456) alex.__high = 170 # print(alex.getwd()) # 程序定义__私有属性,保存为了(_类__属性)的形式 print(alex.__high) ## 在类的外部定义的双下划线方法,可以被调用,格式也有变化。 print(alex.get_pwd()) ret = alex.test2() print(ret) ret()
###############
170 123456 <bound method Person.__test of <__main__.Person object at 0x00000200B052EC50>> {'name': 'alex', '_Person__passwd': 123456, '__high': 170} 私有方法内部调用
小结:
所有的私有,都是在变量左边加双下划线
所有的私有,在类内部随便调用,不能在类外部使用,__dict__是投机取巧的方法
私有包括:私有属性,私有方法,私有静态
几个内置函数
property
伪装代码,让代码看起来更加合理
from math import pi class Circle: def __init__(self,r): self.r = r @property def perimeter(self): return 2 * pi * self.r @property def area(self): return self.r ** 2 * pi c1 = Circle(5) print(c1.area) # 代码经过伪装,名词'类方法'看起来更像是属性更加合理 print(c1.perimeter)
################## 78.53981633974483 31.41592653589793
一个静态属性property本质就是实现了get,set,delete三种方法
set可以理解为修改
delete可以理解为删除
class Foo: @property def AAA(self): print('get的时候运行我啊') @AAA.setter def AAA(self,value): print('set的时候运行我啊') @AAA.deleter def AAA(self): print('delete的时候运行我啊') #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter f1=Foo() f1.AAA f1.AAA='aaa' del f1.AAA ######### get的时候运行我啊 set的时候运行我啊 delete的时候运行我啊
怎么用,比如说
class Goods: def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): # setter要在self,后面加入一个参数,设置得参数 self.original_price = value @price.deleter def price(self): del self.original_price obj = Goods() obj.price # 获取商品价格 obj.price = 200 # 修改商品原价 print(obj.price) del obj.price # 删除商品原价
classmethod 和 staticmethod 类方法,静态方法
classmethon 可以把一个方法变成类方法,进而直接调用。不需要依赖对象
class Goods: __discount = 0.8 # 这里是我们定义的打折 def __init__(self,name,price): self.name = name self.__price = price @property def price(self): return self.__price * Goods.__discount # 返回折扣价格 # def change_discount(self,new_discount): # 修改一个新的折扣 # Goods.__discount = new_discount @classmethod # 把一个方法变成类的方法,这个方法可以被类直接调用。不需要依赖任何对象 def change_discount(cls,new_discount): # 这里在定义类方法得时候,还需要再传入一个参数 cls.__discount = new_discount apple = Goods('apple',5) # apple.change_discount(0.5) # 这里我们使用苹果去定义整个商品的折扣是不合理的 # print(apple.price) Goods.change_discount(0.5) print(apple.price)
staticmethod 可以将一个与类无相关的伪装成类的属性
class Login: def __init__(self,name,password): self.name = name self.pwd = password def login(self):pass @staticmethod def get_usr_pwd(): usr = input('用户名:') pwd = input('密码:') Login(usr,pwd) Login.get_usr_pwd()
反射
大概是将字符串变成参数传递
class Teacher: dic = {'显示课程':'数学','显示班级':'2014届'} def show_price(self): print('工资5000快') @classmethod def func(cls): print('体育老师') ret = getattr(Teacher,'dic') # 1.调用静态属性:类的静态属性可以直接获取 print(ret)
tom = Teacher() ret2 = getattr(tom,'show_price') # 2.调用对象属性:实例化一个类对象然后再获取其对象属性 # print(ret2) ret2() if hasattr(Teacher,'func'): # 一般 hasattr 和 getattr 一起使用,不存在则不报错 ret3 = getattr(Teacher,'func') # 3.调用类方法:类方法的调用,直接调用需要实例化 ret3() {'显示课程': '数学', '显示班级': '2014届'} 工资5000快 体育老师