Python学习之路---面向对象_内置函数
面向对象--内置函数(property\classmethod\staticmethod)
property属性
内置装饰器函数,只在面向对象中使用
作用:将类里的方法,伪装成属性,调用时看起来像是调用属性,而不是方法;
注意:被@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 ret = Circle(5) print(ret.area()) # 调用方法需要添加() print(ret.perimeter()) #将方法伪装成属性,通过@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 ret = Circle(5) print(ret.area) #伪装成属性,直接调用无需添加() print(ret.perimeter)
# 典型面向对象的题 # BMI指数(BMI是计算而来,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解) ''' 成人的BMI数值: 过轻:低于18.5 正常:18.5-23.9 过重:24-27 肥胖:28-32 非常肥胖:高于32 体质指数(BMI) = 体重(kg)/身高^2(m) EX: 70KG/(1.75*1.75) = 22.86 '''
class People: def __init__(self,name,weight,height): self.name=name self.weight=weight self.height=height @property def bmi(self): return self.weight / (self.height**2) p1=People('egon',75,1.85) print(p1.bmi)
BMI指数
为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
ps:面向对象的封装有三种方式: 【public】 这种其实就是不封装,是对外公开的 【protected】 这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开 【private】 这种封装对谁都不公开
python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现
class Foo: def __init__(self,val): self.__NAME=val #将所有的数据属性都隐藏起来 @property def name(self): return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置) @name.setter def name(self,value): if not isinstance(value,str): #在设定值之前进行类型检查 raise TypeError('%s must be str' %value) self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME @name.deleter def name(self): raise TypeError('Can not delete') f=Foo('egon') print(f.name) # f.name=10 #抛出异常'TypeError: 10 must be str' del f.name #抛出异常'TypeError: Can not delete'
一个静态属性property本质就是实现了get,set,delete三种方法
#注意: setter
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.5 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('Apple',5) print(apple.price) Goods.change_discount(0.8) print(apple.price)
staticmethod
作用:在完全面向对象的过程中,如果一个函数既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数变成一个静态方法。
# 例子:如登录实现完全面向对象编程 # 常规写法 class Login: def __init__(self,name,pwd): self.name = name self.pwd =pwd def login(): username = input('username:') password = input('password:') Login(username,password) login() #完全面向对象 class Login: def __init__(self,name,pwd): self.name = name self.pwd =pwd @staticmethod # 将被装饰方法,转为一般函数,可以传参,也可以不传参,(注意:因为是一般函数,所以无需写self) def login(): username = input('username:') password = input('password:') Login(username,password) Login.login()
# 类方法和静态方法,都是类调用 # 对象可以调用类方法和静态方法吗? 可以调用,一般情况下推荐用类名调用 # 类方法有一个默认参数cls 代表这个类 # 静态方法没有默认参数,就像函数一样,也是可以传参,传的是一般参数和 self和cls 不一样
练一练
class Foo: def func(self): print('in father') class Son(Foo): def func(self): print('in son') s = Son() s.func() # 请说出上面一段代码的输出并解释原因?
# 实例化Son类 # 调用func方法 # 因为Son类自身有func方法,所以无需再去Foo类中找,所以直接使用自己的func方法
解答
class A: __role = 'CHINA' @classmethod def show_role(cls): print(cls.__role) @staticmethod def get_role(): return A.__role @property def role(self): return self.__role a = A() print(a.role) print(a.get_role()) a.show_role() # __role在类中有哪些身份? # 以上代码分别输出哪些内容? # 这三个装饰器分别起了什么作用?有哪些区
class A: __role = 'CHINA' # 定义了一个私有静态属性,只能类内使用 @classmethod # 类方法,无须依托对象,即可通过类名调用被装饰的方法 def show_role(cls): print(cls.__role) @classmethod # 类方法,无须依托对象,即可通过类名调用被装饰的方法,修改默认参数 def edit_role(cls,newrole): cls.__role = newrole @staticmethod # 静态方法,被装饰的方法 与对象和类无关 def get_role(): return A.__role @property # 将方法伪装成属性 def role(self): return self.__role A.show_role() A.edit_role('CN') a = A() print(a.role) print(a.get_role()) a.show_role()
解答