目录

未命名

@classmethod

如果只是简单“调用类方法不用实例化”概括,那么这种描述(无论长短)和“为什么要在 Python3 头部添加 #coding: utf-8” 一样,没有意义。

补充:Python3 默认文件编码为 UTF-8 但是读写文件的时候默认是按文件原来编码来的,所以读写文件的时候补上 encoding 参数比较规范,而二进制文件则不需要。

1
2
with open(file, mode="r", encoding="utf-8") as f:
    content = f.read()

一句话描述 @classmethod:创建新实例时需要 数据校验/格式化。

推荐第一种写法,灵活度更高。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Shopping:
    """出门前检查要带的金额:20 <= money <= 100"""
    
    def __init__(self, money) -> None:
        self.money = money

    @classmethod
    def check(cls, money):
        if 20 <= money <= 100:
            return cls(money)
        else:
            raise "money not validate"

    # 创建实例化就校验
    def __new__(cls, money):
        if 20 <= money <= 100:
            obj = object.__new__(cls)
            obj.money = money
            return obj
        else:
            raise "money not validate"

shopping = Shopping.check(50)
shopping = Shopping(-1)

@staticmethod

实际工作的时候我更偏向于将公共函数放在 utils.py,比如 create_folder()、decrypt_base64()、download_file() 等。

一句话概括 @staticmethod:只服务于当前类(其他外部类/函数用不到或关联性较小),放在类里面比较简洁。

1
2
3
4
5
6
class Shopping:
    # 汇率转换
    @staticmethod
    def rmb_to_usd(rate: float, rmb: int):
        usd = rmb / rage
        return usd

@poerty

实际工作用的不多,直接抄 Python中@property和@setter的用法的。

一句话概括:将类方法转为属性更合理的读取值、预处理数据、禁止修改对象值。

将类方法转为属性更合理的读取值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class User():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tag(self):
        return self.name + str(self.age)
        
    @poerty
    def tag2(self):
        return self.name + str(self.age)

user = User('xiao',5)
print(user.tag())
# tag 更像是属性对象,所以使用类属性 user.tag 的方式获取会比 user.tag() 更加的合理。
print(user.tag2)   

预处理数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class User():
    def __init__(self, name, age):
        self.name = name
        self._age = age  # 私有变量

    @property
    def age(self):
        return self._age
        
    @age.setter
    def age(self,n):
        self._age = n + 5

user = User('xiao',0)
# 当执行 user.age = 5 时,@age.setter装饰器下的age函数会将数据+5 后再存入类属性_age中,实现了存入前对数据的预处理。
user.age = 5
print(user.age)  # 结果:10

禁止修改对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class User():
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,n):
        print('数据不能被修改')

user = User('xiao',0)
# 在为 age 赋值时会立即触发 @age.setter 装饰器下的 age 函数中的提示语句或者异常处理语句。
user.age = 5

Refference:

python装饰器@classmethod的深入理解以及它的使用场合 # @classmethod和@staticmethod

Python中@property和@setter的用法