1.封装
什么是封装:
广义上的封装:把变量和函数都放在类中(例:人狗大战中,将狗咬人的函数放到dog类中)
狭义上的封装:把一些变量或者方法隐藏起来,不对外公开
公有的:静态属性,动态属性(方法),对象属性
私有的:__名字
私有静态属性
# 例:class Person: __country = '中国' # 私有的静态属性 # print(__country) # 执行文件会输出结果,因为定义类的时候会开辟一块内存空间存储类中的名字print(Person.__country)# print(Person.__country)# AttributeError: type object 'Person' has no attribute '__country'# 说明:私有的名字 只能在类的内部使用,不能在类的外部使用print(Person.__dict__)# {'__module__': '__main__', '_Person__country': '中国', '__dict__':, '__weakref__': , '__doc__': None}print(Person._Person__country)# 中国# 说明:如果非要在类的外部调用一个私有的名字,name必须是在私有的名字前面加_类名__私有的名字# *****注意:不能使用上面这种方式去调用私有的变量*****#Person.__name = 'xxx'print(Person.__name)# xxxprint(Person.__dict__)# {'__module__': '__main__', '_Person__country': '中国', '__dict__': , '__weakref__': , '__doc__': None, '__name': 'xxx'}# 说明:在类的外部不能定义一个私有变量# 私有的变量:# 在类的内部 如果使用__变量的形式会发生变形,python会自动的为你加上_类名
私有的对象属性
# 私有的对象属性class Person: __country = '中国' def __init__(self, name, pwd): self.name = name self.__pwd = pwd # 私有的对象属性alex = Person('alex', 'alex123')# print(alex.__pwd)# # print(alex.__pwd)# # AttributeError: 'Person' object has no attribute '__pwd'# 私有的对象属性的使用 -- 类中的登录方法class Person: __country = '中国' def __init__(self, name, pwd): self.name = name self.__pwd = pwd # 私有的对象属性 def login(self): if self.name == 'alex' and self.__pwd == 'alex123': print('登录成功')alex = Person('alex', 'alex123')alex.login()# 登录成功
私有的方法
# 私有的方法class Person: def __init__(self):pass def __eat(self): print('eating')alex = Person()# alex.__eat()# alex.__eat()# AttributeError: 'Person' object has no attribute '__eat'# 说明:不希望类中的一些方法,对外提供服务,但可以对内提供服务# 使用场景:用户注册,进行密码转换
总结:在静态属性、对象属性、方法(动态属性)前面加上双下划线都会变成私有的
私有的特点就是只能在类的内部调用,不能在类的外部使用
测试题
# 测试题:实例化s,打印结果是什么# 1.有关方法继承的练习# 说明:就近原则,现在自己的命名空间中找,然后到父类中找class Foo: def __init__(self): self.func() def func(self): print('in Foo')class Son(Foo): def func(self): print('in son')s = Son()# in son# 2.有关方私有法继承的练习class Foo: def __init__(self): self.__func() # self._Foo_func(没有) def __func(self): print('in Foo')class Son(Foo): def __func(self): # _Son_func print('in son')s = Son()# in Foo
2.类中的装饰器方法
三个面向对象的内置函数 -- 三个装饰器函数
classmethod、staticmethod、property
2.1 property
未使用property和使用property的类的比较
# 例 - 圆形类:# 未使用propertyfrom cmath import piclass Cricle: def __init__(self,r): self.r = r def area(self): return self.r ** 2 * pi def perimeter(self): return self.r * 2 * pic = Cricle(3)print(c.area())# 28.274333882308138print(c.perimeter())# 18.84955592153876# 方法 动词 -- 动作或者技能# 名词 圆的面积 圆的周长 圆的半径# 将一个函数伪装成为属性@property# 一旦一个方法添加了@property,就不能使用c.area()调用了from cmath import piclass Cricle: def __init__(self,r): self.r = r @property def area(self): return self.r ** 2 * pi @property def perimeter(self): return self.r * 2 * pic = Cricle(3)print(c.area)# 28.274333882308138print(c.perimeter)# 18.84955592153876
练习1:编写类,求房间的表面积和体积
# 练习:已知房间的长宽高,计算表面积和体积class Room: def __init__(self, length, width , height): self.length = length self.width = width self.height = height @property def area(self): return (self.length * self.width + self.length * self.height + self.width * self.height) * 2 @property def volume(self): return self.length * self.width * self.heightroom = Room(3, 5, 3)print(room.area)# 78print(room.volume)# 45
练习2:property结合__私有的名字,setter更新私有对象属性,deleter删除私有对象属性
# property __私有的名字# 商场打折行为class Goods: def __init__(self,price, discount): self.__price = price self.discount = discount @property #添加property因为不添加括号了,所以不能添加参数了 def price(self): return self.__price * self.discount @price.setter # 使用前提,必须已经price方法,并使用property进行隐藏 def price(self, newprice): self.__price = newprice @price.deleter # 删除price方法,但是并不常用 def price(self): del self.__priceapple = Goods(8, 0.7)print(apple.price)# 5.6apple.price = 10print(apple.price)# 7.0print(apple.__dict__)# {'_Goods__price': 10, 'discount': 0.7}del apple.priceprint(apple.__dict__){ 'discount': 0.7}print(apple.price)# return self.__price * self.discount# AttributeError: 'Goods' object has no attribute '_Goods__price'
2.2classmethod类方法
class Person: Country = '中国人' def func(self): print('当前的角色的国籍是%s' % Person.Country)alex = Person()alex.func()# 当前的角色的国籍是中国人Person.func()# Person.func()# TypeError: func() missing 1 required positional argument: 'self'# 类方法class Person: Country = '中国人' @classmethod # 把func变成一个类方法,这样就不需要实例化对象才能调用类中的方法 def func(cls): # cls是指向类的内存空间 print('当前的角色的国籍是%s' % Person.Country)Person.func()# 当前的角色的国籍是中国人# 说明: 如果某一个类中的方法 并没有用到这个类的实例中的具体属性# 只是用到了类中的静态变量 就使用类方法
2.3staticmethod静态方法
如果一个方法既不会用到对象中的属性,也不会用到类中的属性,就应该被定义成为一个静态方法
# 静态方法staticmethodclass Student: @staticmethod def login(): name = input('name: ') pwd = input('pwd: ') if name == '' and pwd == '': print('实例化')Student.login()# name: alex# pwd: alex123 # 使用场景:在没有创建student对象的时候,进行学员登录 # 如果登录成功,再进行实例化