Python数据类型:类class、反射dataclasses、functools、typing、pydantic

三、类

类型注解(typing、pydantic)

属性可以指定类型注解和默认值。

Python中创建对象不使用new关键字。

python 复制代码
class User:
    name: str
    country: str = "China"
# China
print(User().country)
java 复制代码
// java创建对象使用new关键字
User user = new User();
python 复制代码
# 很多编程语言创建对象都使用关键字new
user = User()

typing

定义类时常结合typing显示指定类型。

  • List[T]:元素类型为 T 的列表

  • Dict[K, V]:键类型 K、值类型 V 的字典

  • Optional[T]:等价于 Union[T, None],表示可以是 T 或 None

  • Union[T1, T2, ...]:允许多种类型之一

  • Any:任意类型(不进行静态类型检查)

python 复制代码
from typing import List, Dict, Optional, Union, Any

class User:
    def __init__(
        self,
        user_id: int,
        name: str,
        tags: List[str],                # 字符串列表
        metadata: Dict[str, Any],       # 键为字符串,值为任意类型的字典
        age: Optional[int] = None,      # 可以是 int 或 None
        role: Union[str, int] = "user"  # 可以是字符串或整数
    ) -> None:
        self.user_id = user_id
        self.name = name
        self.tags = tags
        self.metadata = metadata
        self.age = age
        self.role = role


# 使用示例
if __name__ == "__main__":
    user = User(
        user_id=1,
        name="Alice",
        tags=["admin", "premium"],
        metadata={"signup_date": "2025-01-01", "score": 95},
        age=30,
        role="moderator"
    )
    print(user.name, user.tags)

pydantic

class定义通常还使用pydantic进行设置一些默认值或者参数合法检查。

Field:

  • default:默认值,default=[ ] :所有模型实例会共享同一个列表对象,修改一个实例的 会影响其他实例(经典的可变默认值陷阱),注意列表要用default_factory。
  • default_factory:动态生成,接收任何无参数的 callable,list表示每次自动执行 list(),生成全新空列表。常用于dict、set、datetime.now、uuid4
参数 作用 示例
... (省略号) 必填字段 message: str = Field(...)
default 默认值 session_id: str = Field(default=None)
default_factory 默认工厂 decisions: list = Field(default_factory=list)
description 字段描述 description="用户消息"
ge / le 数值范围 confidence: float = Field(ge=0.0, le=1.0)
min_length / max_length 字符串长度 message: str = Field(max_length=8000)
python 复制代码
class MeetingSummary(BaseModel):
	"""会议纪要"""
	title:str=Field(...,description="会议标题")
	date: str = Field(...,description="会议日期")
	attendees:List[str]= Field(...,description="参会人员")
	summary: str=Field(...,description="会议摘")
	decisions: List[str]=Field(default_factory=list, description="决议事项")
	action_items: List[MeetingAction]= Field(default_factory=list, description="行动顶")
	notes:str=Field(default=None,description="备注")
python 复制代码
from enum import Enum
from pydantic import BaseModel, Field,ValidationError

class Intent(str, Enum):
    """用户意图枚举"""
    CHAT = "chat"            # 闲聊问答
    MEETING = "meeting"      #会议纪要
    UNKNOWN = "unknown"      # 未知

class RouterDecision(BaseModel):
    """路由决策结果"""
    intent: Intent							 # 识别到的意图
    confidence:float = Field(ge=0.0,le=1.0) # 置信度0-1
    reasoning: str                    		# 推理过程
    extracted_info:dict = None        		# 提取的信息

decision =RouterDecision(
	intent=Intent.CHAT,
	confidence-0.95,
	reasoning="用户在进行日常对话"
)	

functools

bash 复制代码
from functools import lru_cache

@lru_cache
def get_settings() -> Settings:
    """获取全局配置单例
    使用 lru_cache 缓存配置对象,避免重复读取 .env 文件。
    """
    return Settings()

实例类型判断

python 复制代码
if isinstance(msg, AIMessage):
	pass
elif isinstance(msg, HumanMessage):
	pass	

多重继承

多个继承使用逗号分隔。

python 复制代码
from enum import Enum

class Intent(str, Enum):
    """用户意图枚举"""
    CHAT = "chat"            # 闲聊问答
    MEETING = "meeting"      #会议纪要
    UNKNOWN = "unknown"      # 未知

self

对象方法必须有参数,而且第一个参数必须是self。注意:self并不是Python的关键字,处于习惯大家都默认使用self,Java中使用关键字this。默认是继承 object ,可以省略。

java 复制代码
public class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

		@Override
    public String toString() {
        return "User{name='" + name + '\'' + ", age=" + age + '}';
    }
}
py 复制代码
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __str__(self):
        return f"User(name={self.name}, age={self.age})"

Python初始化方法 __init__ 相当于 Java的构造方法,只不过不用在最上面声明属性,相对来说更简洁。

py 复制代码
import keyword

# 查看Python中的关键字列表
print(keyword.kwlist)

魔法方法

Python中方法名以双下划线__作为前缀和后缀的方法叫做魔法方法,魔法方法相当于Java的接口方法,具有特定的功能。

  • __new__:实例化方法,先执行__new__再执行__init__。
  • __init__:初始化方法,常用于类的构造方法,例如给属性初始化None, 如 self.xxx = None。
  • __str__:toString()方法。
  • __eq__:用于比较两个对象是否相等。
  • __iter__:迭代器通常与__next__配合使用。
  • __next__:表示迭代器对应的next()方法。
  • __add__:加法运算符 +
  • __or__:或运算符 |
  • __mul__:乘法运算 *,如 字符串乘以数字,print("-" * 20)
  • __mod__: 取余,self % value,常见的字符串拼接,print("name=%s age=%d" % (name, age))
  • __gt__:大于 >
  • __ge__:大于等于 > =
  • __lt__:小于<
  • __le__:小于等于 <=
  • __call__:让"对象像函数一样可调用"
python 复制代码
class Adder:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return x + self.n

add5 = Adder(5)
# 这里 add5 是对象,但可以像函数一样调用
print(add5(10))  # 15

有了魔法方法,只要类中实现了魔法方法就可以通过符号来操作类了,如 对象之间比较大小,重写__or__来实现管道 | 的作用。

python 复制代码
class MyList:
    def __init__(self, items=None):
        self.items = items or []

    def __or__(self, other):
        """实现 self | other 操作"""
        # 创建新实例,避免修改原对象
        new_list = MyList(self.items.copy())
        new_list.items.append(other)
        return new_list

    def __repr__(self):
        return f"MyList({self.items})"


# 使用示例
ml = MyList([1, 2, 3])
ml2 = ml | 4 | 5 | 6  # 链式调用

print(ml)  # MyList([1, 2, 3]) - 原对象不变
print(ml2)  # MyList([1, 2, 3, 4, 5, 6])

访问权限约定

Python所提倡的用更多的符号来代替关键字,在Java中定义私有变量要使用private关键字。

  • 私有属性在属性名前使用双下划线命名规则。如:__password
  • 类的私有方法也是在方法名前使用双下划线前缀。如 __set_password
  • 访问私有属性或者私有方法的规范是:_类名__私有成员
py 复制代码
class Person:
    country = "China"

    def say_hello(self):
        print("I'm Chinese")


class Student(Person, Chinese):
    name = None
    age = 0
    __weight = 60

    def __init__(self):
        pass

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

    def say_hello(self):
    			# 方式一:显式调用父类方法使用super()方法,而不是super关键字
    		  super().say_hello()
    		  # 方式二:通过类名指定父类的方法(多继承时此种方式更加直观)
    		  Person.say_hello(self)
    		  
        print("I'm Student")

    def __private_func(self):
        print("私有函数")

    def __add__(self, other):
        return Student(self.name + other.name, self.age + other.age)

zhangsan = Student("zhangsan", 26)
zhangsan.say_hello()
super(Student, zhangsan).say_hello()

lisi = Student("lisi", 24)
zhangli = zhangsan + lisi
print(zhangli.age)

# 访问私有属性和方法
print(zhangsan._Person__gender)
zhangsan._Person__private_func

# 多重继承时,当方法名重名时优先调用子类的方法,然后再按照继承的先后顺序优先使用前面的顺序,__mro__返回父类的继承顺序
# MRO(method resolution order)方法解析顺序
print(zhangsan.__mro__)

抽象方法 @abstractmethod

Python认为一个方法没有方法体,即方法体为pass就可以认为是一个抽象方法,Python一直在倡导约定大于语法,所以也没有提供什么语法强制校验,毕竟程序员要对自己写的代码负责。Python虽然没有把抽象方法作为一级语法,但是也可以在运行时检测抽象方法有没有实现,没有实现就抛异常,需要通过abc模块来检查。TypeError: Can't instantiate abstract class Chinese with abstract method hello

Python中只有class关键字,没有接口interface关键字,Python认为一个类中的所有方法的方法体都是pass,那么这个类就算一个接口。Python中也没有接口,抽象类就是接口,这也是Python简化代码的一个重要提现。

python 复制代码
from abc import ABC, abstractmethod


class Person(ABC):
    def __init__(self, name=None, age=None):
        self._name = name
        self._age = age

    @abstractmethod
    def hello(self):
        pass


class Chinese(Person):
    pass


if __name__ == '__main__':
    chinese = Chinese()
    chinese.hello()

静态方法 @staticmethod 和类方法 @classmethod

  • @staticmethod: 方法逻辑与类相关,但不需要任何类或实例数据时使用(如工具函数),参数列表中第一个参数不需要 cls或self,直接定义真实的参数,类似普通函数,类似于Java中的StringUtils.isBank()
python 复制代码
class MathUtils:
    @staticmethod
    def is_even(number):
        return number % 2 == 0
    
    @staticmethod
    def validate_email(email):
        return "@" in email and "." in email

# 使用
print(MathUtils.is_even(10))  # True
print(MathUtils.validate_email("test@example.com"))  # True

@classmethod: 需要访问或修改类状态、实现多态工厂方法时使用

python 复制代码
class Person:
    count = 0
    
    def __init__(self, name):
        self.name = name
        Person.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count  # 访问类属性
    
    @classmethod
    def from_birth_year(cls, name, birth_year):
        """工厂方法:根据出生年份创建实例"""
        age = 2026 - birth_year
        return cls(name, age)  # 创建实例

# 使用
print(Person.get_count())  # 0
person = Person.from_birth_year("张三", 2000)

多态(鸭子类型🦆)

鸭子类型(Duck Typing)是指如果它走起来像鸭子,叫起来叫鸭子,那么它就是鸭子。

在鸭子类型中,关注的是对象的行为而不是对象的类型。

在Python中多态不依赖是否有继承关系,只要有相同的方法即可。Python中的类型只是一种注释,一种提示,并不会导致编译错误,所以多态的所谓类型在Python中没有任何作用。

Python中的多态更像是Java中的接口中的多态,拥有相同的方法。

类型对象

在 Python 里,类本身也是对象,所以可以像普通值一样当作实参传进去。

"类型对象"传给了构造函数,供内部做检查/反射/实例化等。

python 复制代码
class State:
    name: str

def print_state(state: type):
    print(state)

# <class '__main__.State'>
print_state(State)

dataclasses 类似于Java的反射,将类名作为参数传参 MiniGraph(State) ,类似于Java中的Class对象,MiniGraph(State.class)

python 复制代码
from dataclasses import dataclass, fields

# 1) 定义一个"状态类型"
@dataclass
class State:
    count: int
    name: str

# 2) 一个接收"类型"的类
class MiniGraph:
  def __init__(self, state_type: type):
      self.state_type = state_type  # 保存传入的类

      # 用这个类做一些事情:读取字段信息(反射)
      self.field_names = [f.name for f in fields(state_type)]

  def create_state(self, **kwargs):
      # 用传入的类来创建实例
      return self.state_type(**kwargs)

  def show_schema(self):
      print("state_type:", self.state_type.__name__)
      print("fields:", self.field_names)

# 3) 传入"类名"作为实参
graph = MiniGraph(State)   # 注意:不是 State(),而是 State
graph.show_schema()

s = graph.create_state(count=1, name="Alice")
print(s)
print(type(s))
"""
  state_type: State
  fields: ['count', 'name']
  State(count=1, name='Alice')
  <class '__main__.State'>
"""

关键点:

  1. State 是类对象(type instance),可传参。
  2. State() 才是实例对象。
  3. 这种写法常用于框架里:传类型给框架,框架再基于类型做校验、序列化、自动建模等。
相关推荐
lzhdim2 小时前
C#性能优化技巧
开发语言·性能优化·c#
森G2 小时前
TypeScript环境搭建---------------基于windows10
开发语言·typescript
weixin_428005302 小时前
C#调用 AI学习从0开始-第1阶段(基础与工具)-第5天完善请求结构
windows·学习·c#·ai请求结构
wand codemonkey2 小时前
(三十)web应用+【核心】+【规矩】+【原理】
java·开发语言·前端
阿部多瑞 ABU2 小时前
运动会智能编排系统 - 完整详细需求规格说明书
python·贪心算法·vue·html
阿正的梦工坊2 小时前
Kotlin:现代编程语言的优雅之选
android·开发语言·kotlin
threelab2 小时前
潮玩DIY设计平台技术解析:基于Babylon.js的3D定制化实践
开发语言·javascript·3d
郝学胜-神的一滴2 小时前
Qt 高级开发 007: 图片查看器案例
开发语言·c++·qt·程序人生·开源软件
白开水就盒饭2 小时前
《数据挖掘(主编:吕欣、王梦宁)》读书笔记总结
python·mysql·数据挖掘·知识图谱