Python-进阶特性篇(函数与OOP)
1、函数篇
定义:可以重复使用的一段代码
def 函数名(形参列表): //实现特定功能的多行代码 [return [返回值]]
- 函数名指向函数对象,传递函数->函数名,调用执行函数->函数名(实参)
- 参数介绍
- 顺序规则:必选 > 默认 > *args > 命名关键字 > **kw
| 参数类型 | 定义--形参 | 调用--实参 |
| 必选参数 | func(name1, name2) |
1、func(value1, value2)--按位置顺序传递值 2、func(name1=value, name2=value)--按参数名传递值 |
| 默认参数 | func(name1 = value1, name2 = value2) | 1、func()--没有传入实参,使用形参默认值 |
| 可变参数-位置参数 | func(*args) |
1、func(value1, value2)--args[0]为value1,args[1]为value2 2、接受任意个实参 |
| 可变参数-关键字参数 | func(**kw) |
1、func(name1 = value1, name2 = value2) 2、kw[name1] = value1 3、接受任意个键值对实参 |
| 万能参数 | func(*args, **kw) |
1、接受任意的实参,包括普通实参和键值对实参 |
- 返回值
- return 返回值:返回多个值时,实际上返回的是一个元组
- 没有return:返回None
- 匿名函数:方便用来表示仅包含1个表达式的函数
函数名 = lambda [形参列表]:expression 1、只能有1个表达式(常用于sort()、filter()等高阶函数) 2、表达式的结果就是返回值
-
LEGB 规则:查找变量时遵循的优先级顺序,Local(局部) -> Enclosing(嵌套) -> Global(全局) -> Built-in(内置)
- Local(局部作用域):当前函数(或代码块)内部定义的变量。
- Enclosing(嵌套作用域):嵌套函数(闭包)的外层函数作用域。
- 内层函数可以访问外层函数的变量,但外层函数不能访问内层函数的变量。
- 逐层向外查找,找到即停止。
- 内层函数中修改外层(非全局)函数的变量:必须使用
nonlocal关键字
- 内层函数可以访问外层函数的变量,但外层函数不能访问内层函数的变量。
- Global(全局作用域):当前模块(.py 文件)的顶层(全局)定义的变量。
- 函数内部读取全局变量:直接读取即可
- 函数内部修改全局变量:必须使用
global关键字声明
- Built-in(内置作用域):Python解释器内置的变量和函数
- Local(局部作用域):当前函数(或代码块)内部定义的变量。
2、类和对象篇
-
类(Class):是创建对象的蓝图或模板。它定义了一组属性(数据,用变量表示)和方法(行为,用函数表示)。
-
类本身是一个逻辑上的抽象概念,例如“人类”定义了所有人类共有的特征和行为。
-
-
对象(Object):是根据类这个模板创建出来的具体实体(即实例)。
-
它拥有类所定义的属性和方法,但每个对象的属性值可以是独立的(例如,一个苹果是红的,另一个苹果可能是绿的)。对象在程序运行时存在于内存中。
-
构造方法(Constructor):类中一种特殊的方法,在实例化时被自动调用,用于初始化新创建对象的状态或属性。
-
实例化(Instantiation):以类为模板,在内存中“生产”出一个新对象的过程。
-
- cls:类方法的第一个参数,指向类本身
- self:实例方法的第一个参数,指向实例对象本身
- super():返回一个代理对象,用于在继承关系中按照方法解析顺序(MRO) 自动查找并调用下一个类的方法。(访问父类方法)
- 关键作用:解决多继承中的方法调用冲突,确保父类方法被正确调用。
- super(B, self):表示从B类在MRO顺序中的下一个类开始查找方法。self则提供了实例上下文。
- MRO(方法解析顺序):Python计算出的一个类继承顺序列表(可通过类名.__mro__查看),super()严格按照此顺序进行方法查找。
class A: def show(self): print("A") class B(A): def show(self): super().show() # 调用MRO中B的下一个类(即A)的show print("B") print(B.__mro__) #(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>) b = B() b.show() #先打印A,再打印B
class 类名(父类1,父类2): 多个属性... 多个方法...
- 元类、metaclass:控制类的创建(可以指定metaclass改变类的生成方式--仅做了解)
- 创建对象:instance_demo = 类名()
- 枚举类:对象个数固定的类(周末类、月份类),需要继承Enum
- 类的成员:属性+方法
- 属性介绍
- 类属性:类内部、方法之外定义的变量
- 实例属性:方法内部,使用"self.变量名"定义的变量
- 局部属性:方法内部,以"变量名=变量值"定义的变量
- 特殊属性
- __doc__:类的描述信息\类前面的注释
- __class__:类的类型、比如<class '__main__.b'>
- __name__:类名、对象名
- 实例方法、类方法(@classmethod)、静态方法(@staticmethod)
| 实例方法 | def study(self): print(self,"正在学Python") |
Python解释器使用self判断调用方法的是哪个对象 1、第一个参数必须是 2、通过 3、访问:instance_demo.study() 4、使用场景:几乎所有需要处理对象特有数据的操作,都应该定义为实例方法。 |
| 静态方法 |
@staticmethod def study(): |
1、本质上就是一个放在类里的普通函数。 2、不能直接访问实例属性或类属性 3、使用场景:一个独立的工具函数 |
| 类方法 |
@classmethod def study(cls): |
1、使用 2、通过 3、使用场景:工厂方法+操作类属性 # 工厂方法 @classmethod def from_string(cls, desc): # 假设描述是 "name:旺财" name = desc.split(":")[1] return cls(name) # 创建并返回不同的实例 |
- 常用特殊方法(魔术方法)
- 以下这些以双下划线开头和结尾的特殊方法,用于在特定操作发生时(如对象被调用、属性被访问时)自动触发,可以让我们自定义对象的行为。
- 以下这些以双下划线开头和结尾的特殊方法,用于在特定操作发生时(如对象被调用、属性被访问时)自动触发,可以让我们自定义对象的行为。
| 构造方法 |
def __new__(self,...): 代码块 |
创建并返回对象 |
| 初始化方法 |
def __init__(self,...): 代码块 |
对生成的对象进行初始化 |
| call方法 |
def __call__(self,...): 代码块 |
1、instance_demo():调用对象时,访问__call__() class Demo: def __call__(self): print("对象被调用了!") def __getattr__(self, name): return f"你访问的属性 '{name}' 不存在" |
| 额外属性方法 |
def __getattr__(self,...): 代码块 |
1、instance_demo.other_attr:访问的属性不存在时,访问 __getattr__() |
| 字符串方法 |
def __str__(self,...): 代码块 |
1、print(instance_demo):打印对象时,访问__str__() 2、默认的__str__()还会访问__repr__() 3、__repr__():返回对象信息 比如<__main__.B object at 0x0000029B0BEB22B0>
|
- 三大特征:封装、继承、多态
| 封装 |
将类的某些信息隐藏在类内部,不允许外部程序直接访问,只能通过该类提供的方法来访问
# 将get_name和set_name方法变成属性调用 class Person: def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, value): self._name = value |
1、将name定义为私有 2、定义方法访问name def set_name(self,name): |
| 继承 |
在已存在类的基础上进行扩展产生新类 1、子类拥有父类的所有成员 2、子类可以重写父类方法 --访问父类被重写的方法:父类.方法名(子类对象) |
class 类名(父类1, 父类2, ...): #类定义部分 |
| 多态 |
相同方法在父类及其各个子类中具有不同的实现 # 1. 定义父类 Animal class Animal: def __init__(self, name): self.name = name # 父类中定义了一个通用方法 speak,但暂时没有具体实现 def speak(self): # 可以抛出一个异常,提醒子类必须重写此方法 raise NotImplementedError("子类必须实现 speak 方法") # 2. 定义不同的子类,并重写父类的 speak 方法 class Dog(Animal): def speak(self): # 子类提供了自己的具体实现 return f"{self.name} 汪汪叫!" class Cat(Animal): def speak(self): return f"{self.name} 喵喵叫!" # 3. 定义一个“接口”函数,它接收任何 Animal 类型的对象 def make_animal_speak(animal): # 注意:这里我们只关心对象有没有 speak 方法,而不关心它具体是什么类型 print(animal.speak()) # 4. 创建不同的动物实例 dog = Dog("旺财") cat = Cat("咪咪") # 5. 调用同一个函数,传入不同的对象,表现出不同的行为 —— 这就是多态! make_animal_speak(dog) # 输出:旺财 汪汪叫! make_animal_speak(cat) # 输出:咪咪 喵喵叫! |
1、前提:继承+子类重写父类方法 2、使用不同子类对象,可访问不同的实现 3、程序运行时根据传入的实际对象类型(Dog还是Cat), 4、自动找到并执行对应类中重写的 |
本文来自博客园,作者:Fēngwèi,转载请注明原文链接:https://www.cnblogs.com/fengwei-blogs/p/21077440

浙公网安备 33010602011771号