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()

解答

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry's-Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值