1. @property -> 将类方法伪装成类属性

  • 一般定义为属性的都是名词,方法的都是动词,但是有些情况方法名为名词且有想在外部以属性的形式调用,这时候就要使用 @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

c = Circle(5)
print(c.perimeter)  # 查看伪装属性
print(c.area)  # 查看伪装属性

  • @方法名.setter 伪修改属性(伪装属性的传值)

    • 如果设置了该装饰器那么就会先执行该装饰器然后再执行被@property所被装饰的函数里面的代码

from math import pi

class CAttr:
    def __init__(self, num):
        self.__num = num

    @property  # 伪装成类属性
    def num(self):
        return self.__num + 10

    @num.setter  # 伪装属性的传值
    def num(self, new_num):
        self.__num = new_num

c = CAttr(5)
print(c.num)  # 15
c.num = 20
print(c.num)  # 30  先执行被@方法名.setter所装饰的函数,然后再执行被@property所被装饰的函数

  • @方法名.deleter 伪删除属性

    • 遇见了 del 只是执行被 @方法名.deleter 所装饰的函数里面的代码,不是删除伪装属性

from math import pi

class CAttr:
    def __init__(self, num):
        self.__num = num

    @property  # 伪装成类属性
    def num(self):
        return self.__num + 10

    @num.deleter
    def num(self):
        del self.__num

c = CAttr(5)
print(c.num)  # 15
del c.num  # 遇见了 del 只是执行被 @方法名.deleter 所装饰的函数里面的代码,不是删除伪装属性
print(c.num)  # 没有该属性报错

2. @classmethod -> 类方法

  • 类方法和方法要去分开,可以直接被类调用的方法才叫类方法

  • 把一个方法变成一个类中的方法,这个方法就直接可以被类调用(类名.方法名()),不需要依托任何对象

  • 如果使用了 @classmethod 装饰器,那么被装饰的函数的第一个参数默认是 cls 代表的当前类

  • cls 和 self 的区别: cls表示当前这个类的本身,self表示一个具体的实例本身(即: 实例化出来的对象 等同于 self)

  • 类和对象都可以调用方法,但是不建议通过对象去调用

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, discount):
 # cls 代表当前类
        cls.__discount = discount

apple = Goods('苹果', 5)
orange = Goods('橙子', 10)
print(apple.price)  # 4.0 折后价
print(orange.price)  # 8.0 折后价

# apple.change_discount(0.5) 不应该以对象的的形式调用该方法,虽然可以这样使用但是不符合,因为 discount 是静态属性(公共属性)所以应该使用 @classmethod 装饰器将 change_discount 方法变成类的方法以 Goods.change_discount(0.5) 形式调用才符合

Goods.change_discount(0.5)  # 直接通过 类.方法名 调用类方法

print(apple.price)  # 2.5
print(orange.price)  # 5.0

3. @staticmethod -> 静态方法

  • 如果一个函数和类没有关系,也和对象没有关系,且又要定义在类中可以被类直接调用,那么就用staticmethod将这个函数变成一个静态方法

  • 静态方法没有默认参数就像函数一样

  • 类和对象都可以调用静态方法,但是不建议通过对象去调用

class Login:
    def __init__(self, name, pwd):
        self.name = name
        self.pwd = pwd

    def login(self): pass

    @staticmethod  # 设置静态方法
    def get_usr_pwd():
        usr = input('用户名:')
        pwd = input('密码:')
        Login(usr, pwd)

Login.get_usr_pwd()  # 调用静态方法