类属性

生活中总会出现这样一种特征,一类事物共有的共同的特征,Python语法中提供了类型属性(简称类属性)描述表现这样的特征。

什么是类属性

定义给类型的属性,直接描述一类事物的特征,而不是具体某个对象的特征。

类属性的声明

类属性,声明在类型的内部,方法的外部。

class Person:
    """人的类型"""

    # 类属性
    max_age = 150

    def __init__(self, name, age):
        self.name = name
        self.age = age

类属性的特点

类属性描述了一类事物的特征,所以可以被这个类型创建的所有对象去访问(不能修改)

类属性的访问及修改

class Person:
    max_age = 150

    def __init__(self, name, age):
        self.name = name
        self.age = age

# 类属性的访问
# 1. 通过 类名.类属性 访问
>>> print(Person.max_age)
150

# 2. 通过 对象.类属性 访问
>>> man = Person("tom", 35)
>>> man.max_age
150

# 类属性的修改
# 通过 类名.类属性 修改
>>> Person.max_age = 130
>>> print(Person.max_age)
130

类属性的适用场景

类属性的出现,主要是用来描述一类事物共同的特征,如果在项目开发中,出现了类似的特征,要求所有对象都能遵循满足同一个特征数据,考虑适用类属性声明这个特征!

类方法

基本语法

class 类型名称:

    ...
    
    @classmethed
    def 类方法名称(cls, [形参]):
        pass
  • 类方法,也是一种方法,遵循方法的命名规范
  • 类方法,需要在方法上边加上 @classmethed 装饰器声明,表示这是一个类方法
  • 类方法,第一个参数 cls 表示的是当前类
  • 类方法可以访问和修改类属性,通过 cls 直接访问和修改

类方法的调用执行

类方法和类属性一样,推荐直接通过 类名.方法名调用执行

类方法属于一类事物的共同行为,所以通过对象也可以调用

什么时候声明类方法

项目中的某个类型出现了一种行为,和具体的对象无关,此时这样的行为方法,就可以被声明为类方法。

类属性的封装,属性的 set/get 方法必须通过类方法来实现

静态方法

基本语法

class 类名:
  ...

  @staticmethod
  def get_current_time():
    return datatime.now()

什么时候声明静态方法

项目开发过程中,出现了一些功能性的方法,如获取当前系统时间,如此简单之行为,抽取对象声明类型,反倒有过度设计的嫌疑!

注意:面向对象的开发中,不要为了面向对象去专门强行设计类型,很容易造成过度设计!

1. 声明函数实现

面向对象的项目中,如果出现了一些实现独立的小功能行为,可以将这样的功能声明成函数在项目中调用执行(面向过程 面向对象 混合开发

  • 优点:函数式的实现,开发过程中适用方便,哪里需要哪里声明哪里调用!
  • 缺点:如果没有足够的项目规范约束,项目中声明的多个函数到处都是不好维护!

2. 静态方法实现

类似获取时间这样的功能性函数,如果抽取对象声明类型比较繁琐,Python语法中针对这样的函数提供了一个特殊的方法:静态方法。包含在任意一个类型中,通过类型统一管理,可以通过类型名称直接调用,但是静态方法不能访问实例属性,也不能访问类型属性,只起到了函数的作用!

静态方法深入浅出

  • 静态方法声明在类型中,使用 @staticmethod 声明
  • 静态方法既不能访问实例属性,也不能访问类属性,只起到函数的作用
  • 静态方法推荐通过 类名调用执行
  • 如果一个方法既不访问对象数据也不访问类数据,考虑使用静态方法

小结

实例方法 类方法 静态方法
访问实例属性 Y N N
访问类属性 Y Y N

魔法方法

什么是魔法方法

魔法方法如同它的名字一样神奇,是指哪些Python内部已经包含的,被双下划线所包围的方法,这些方法在进行特定的操作时会被自动调用。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        """当对象被打印时调用"""
        return f"name is {self.name}, age is {self.age}"

tom = Person("tom", 18)
print(tom)
# name is tom, age is 18

基础魔法方法

魔法方法名 描述
new(cls) 构造方法
init(self) 初始化方法
call(self[,…]) 允许一个对象像函数一样被调用:x(a,b)调用x.__call__(a,b)
len(self) 定义当被len()调用时的行为
repr(self) 定义当被repr()调用时的行为
str(self) 定义当被str()调用时的行为
hash(self) 定义当被hash()调用时的行为

属性相关

魔法方法名 描述
getattr(self,name) 定义一个当用户试图获取一个不存在的属性时的行为
getattribute(self, name) 定义当该类的属性被访问时的行为
setattr(self, name, value) 定义当一个属性被设置时的行为
delattr(self, name) 定义当一个属性被删除时的行为
dir(self) 定义当 dir() 被调用时的行为

比较操作符

魔法方法名 描述
lt(self, other) 定义小于号的行为:x < y 调用 x.__lt__(y)
eq(self, other) 定义等于号的行为:x == y 调用 x.__eq__(y)
ne(self, other) 定义不等号的行为:x != y 调用 x.__ne__(y)
gt(self, other) 定义大于号的行为:x > y 调用 x.__gt__(y)

算术运算符

魔法方法名 描述
add(self, other) 定义加法的行为:+
sub(self, other) 定义减法的行为:-
mul(self, other) 定义乘法的行为:*
truediv(self, other) 定义真除法的行为:/

增量赋值运算

魔法方法名 描述
iadd(self, other) 定义赋值加法的行为:+=
isub(self, other) 定义赋值减法的行为:-=
imul(self, other) 定义赋值乘法的行为:*=
itruediv(self, other) 定义赋值真除法的行为:/=

类型转换

魔法方法名 描述
int(self) 让当前对象支持 int() 类型转换操作
float(self) 让当前对象支持 float() 类型转换操作
bool(self) 让当前对象支持 bool() 类型转换操作
str(self) 让当前对象支持 str() 类型转换操作

… more and more

反射方法

什么是反射方法

反射方法,就是不通过方法名称调用方法,而是通过一个字符串反向解析得到方法对象执行方法的过程。

# 常规
Object.study()  # 执行了 study() 方法

# 反射
method = getattr(Object, "study")
method()

常见的反射方法

魔法方法名 描述
hasattr(obj, attr) 判断目标对象中是否包含指定的属性或者方法
getattr(obj, attr) 从目标对象中获取执行名称的属性或者方法
setattr(obj, attr, value) 获取并执行目标对象中的属性或者方法
delattr(obj, attr) 从目标对象中删除对应的属性或者方法