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__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} print(Person._Person__country) # 中国 # 说明:如果非要在类的外部调用一个私有的名字,name必须是在私有的名字前面加_类名__私有的名字 # *****注意:不能使用上面这种方式去调用私有的变量***** # Person.__name = 'xxx' print(Person.__name) # xxx print(Person.__dict__) # {'__module__': '__main__', '_Person__country': '中国', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__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的类的比较
# 例 - 圆形类: # 未使用property from cmath import pi class Cricle: def __init__(self,r): self.r = r def area(self): return self.r ** 2 * pi def perimeter(self): return self.r * 2 * pi c = Cricle(3) print(c.area()) # 28.274333882308138 print(c.perimeter()) # 18.84955592153876 # 方法 动词 -- 动作或者技能 # 名词 圆的面积 圆的周长 圆的半径 # 将一个函数伪装成为属性@property # 一旦一个方法添加了@property,就不能使用c.area()调用了 from cmath import pi class 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 * pi c = Cricle(3) print(c.area) # 28.274333882308138 print(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.height room = Room(3, 5, 3) print(room.area) # 78 print(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.__price apple = Goods(8, 0.7) print(apple.price) # 5.6 apple.price = 10 print(apple.price) # 7.0 print(apple.__dict__) # {'_Goods__price': 10, 'discount': 0.7} del apple.price print(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静态方法
如果一个方法既不会用到对象中的属性,也不会用到类中的属性,就应该被定义成为一个静态方法
# 静态方法staticmethod class Student: @staticmethod def login(): name = input('name: ') pwd = input('pwd: ') if name == '' and pwd == '': print('实例化') Student.login() # name: alex # pwd: alex123
# 使用场景:在没有创建student对象的时候,进行学员登录
# 如果登录成功,再进行实例化