一、封装
【封装】隐藏对象的属性和实现细节,仅对外提供公共访问方式。
【私有变量】: __名字 (称为私有化)
私有化了之后,就不能能从类的外部直接调用了。
静态属性、方法、对象属性都可以私有化,这种私有化只是从代码级别做了变形,并没有真的约束。
用到私有的场景 :
1.隐藏起一个属性 不想让类的外部调用
2.我想保护这个属性,不想让属性随意被改变
3.我想保护这个属性,不被子类继承
私有化后的调用:
class Person:
__key = 123 私有静态属性
def __init__(self,name,passwd):
self.name = name
self.__passwd = passwd 私有属性
def __get_pwd(self): 私有方法
return self.__passwd 只要在类的内部使用私有属性,就会自动的带上_类名
def login(self): 正常的方法调用私有的方法
self.__get_pwd()
alex = Person('alex','alex3714')
print(alex._Person__passwd) _类名__属性名
print(alex.get_pwd())
对象的私有属性、类中的私有方法、类中的静态私有属性:所有的私有的 都不能在类的外部使用
封装使用栗子:
class Room:
def __init__(self,name,length,width):
self.__name = name
self.__length = length
self.__width = width
def get_name(self):
return self.__name
def set_name(self,newName): 改名字
if type(newName) is str and newName.isdigit() == False:
self.__name = newName
else:
print('不合法的姓名')
def area(self): 面积
return self.__length * self.__width
jin = Room('金老板',2,1)
print(jin.area()) 2
jin.set_name('2') 不合法的姓名
print(jin.get_name()) 金老板
这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了(原则上不允许)
二、property
内置装饰器函数,只在面向对象中使用 可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
使用栗子:
当不使用@property时:
from math import pi
class Circle:
def __init__(self,r):
self.r = r
def perimeter(self): 圆的周长
return 2*pi*self.r
def area(self): 圆的面积
return self.r**2*pi
c1 = Circle(5)
print(c1.area) <bound method Circle.area of <__main__.Circle object at 0x008DF150>>
print(c1.perimeter) <bound method Circle.perimeter of <__main__.Circle object at 0x008DF150>>
当使用@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) 78.53981633974483
print(c1.perimeter) 31.41592653589793
注意:此时的特性area和perimeter不能被赋值
c.area=3 为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''
2.1 @方法名.setter(对类的对象修改)
使用栗子:
class Person:
def __init__(self,name):
self.__name = name
@property
def name(self):
return self.__name + 'sb'
@name.setter
def name(self,new_name):
self.__name = new_name
tiger = Person('泰哥')
print(tiger.name) 泰哥sb
tiger.name = '全班'
print(tiger.name) 全班sb
使用格式:
2.2 @price.deleter(对类的对象删除)
栗子:
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):
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 类方法
作用:把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象 使用情况:当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法
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
@classmethod
def change_discount(cls,new_discount): 修改静态属性:折扣
cls.__discount = new_discount
apple = Goods('苹果',5)
print(apple.price)
Goods.change_discount(0.5)
print(apple.price)
类方法:有一个默认参数 cls 代表这个类 cls
四、staticmathod 静态的方法
在完全面向对象的程序中,如果一个函数 既和对象没有关系 也和类没有关系 那么就用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()
静态方法:没有默认的参数 就象函数一样
对象可以调用类方法和静态方法么? 可以,一般情况下 推荐用类名调用