Loading... # Python类的相关名词解释 ## 前言 使用Python一年多了,说实话对于Python的类与对象和相关专有名词还是不知道是什么? 记得当初看视频自学的时候,记得是讲过,但是都是学了就忘了。 所以,网上搜搜资料写写示例来总结一下Python类与对象 ## 相关专有名词 1. 类 2. 实例 3. 类属性 4. 实例属性 5. 实例方法 6. 类方法 7. 静态方法 ## 类(Class) 『类』可以比作一张设计图纸,它是创建实例的模板 ## 实例(Instance) 通过图纸(类)创造出来的对象,同一个类的不同实例是互不影响的。 > 类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响; > > 方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据; > > 通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。 ## 类属性 为类绑定绑定的属性被成为『类属性』,可以直接在`class`中定义属性 - 定义类属性 ```python class Robot(object): # 类属性 name = "危险流浪者" version = 4.0 ``` - 使用类属性 ```python # ... Robot.name # output: 危险流浪者 Robot.version # output: 4.0 r = Robot() r.name # output: 危险流浪者 ``` 类属性的调用: 1. 构建实例后,通过`实例.属性`方式调用 2. 直接通过`类.属性`的方法调用  可以对构建后的实例的属性进行赋值并且再次通过`实例.类属性`的方式调用,输出的是我们新赋的值。 **实例属性的优先级大于类属性**  重新赋值后,当我们将新赋值的实例属性从内存中删除后,再次通过`实例.类属性`访问,可以看到是最初的值  > 从上面的例子可以看出,在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。 ## 实例属性 `类`相当与一个模板,假设现在有一个机器人模板(类),我们可以通过这个类,构建出机器人实例,我们为了个性化,每个人都想自定义机器人的名字。 ```python class Robot(object): def __init__(self, name): # 实例属性 self.name = name robot1 = Robot(name="暴风赤红") robot2 = Robot(name="危险流浪者") ``` 再来解释一下为什么叫做『实例属性』? 通过`isinstance`,可以知道`self`就是`Robot`类的一个实例  可以通过`实例.属性`的方法访问『实例属性』,如图:  ## 实例方法 通过上面『实例属性』的介绍,也不难理解『实例方法』的调用方式——`实例.方法` 所以,如果需要调用一个类的『实例方法』则需要先由`类`构建出一个`实例`之后,再通过`实例.方法`的方式调用,如图:  ```python robot = Robot(name="暴风赤红") # 构建实例 robot.fly() # 实例方法 ``` 关于`self`,在『实例属性』中也讲过,它就是当前类的一个实例 ## 类方法 实例方法通过实例调用,那『类方法』肯定就是通过类调用咯! 类方法的定义需要用到`classmethod`装饰器,这个装饰器会自动将当前`类`作为**参数**传给『类方法』的第一个**位置参数** - 定义类方法 ```python class Demo(object): @classmethod def class_method(cls): pass ``` 在上方代码中,`cls`就是`Demo`类,来验证一下  `d` 是`Demo`类的一个实例,将`d`作为参数传入类方法中,判断一下`d`是不是`cls`的实例,结果是`True`,所以`cls`是`Demo`类。 **注意:`cls`这个参数名,是可以自定义,推荐就用`cls`,`self`同理** - 使用类方法 使用类方法时,可以不用构建类的实例,通过`类.类方法`即可调用 ```python class Demo(object): @classmethod def class_method(cls): print(111) Demo.class_method() # output: 111 ``` **举例:** 接着『实例方法』的例子继续举例: 机甲需要人来进入之后,选择要操控的机甲,最后才启动起飞  调用`Robot类`的`enter类方法`并传入`username`参数 在`enter`方法中,通过`cls(Robot类)`构建了`“危险流浪者”(实例)`,最后调用实例方法`fly`起飞 ## 静态方法 静态方法与类方法一样,不需要创建实例再调用,通过`类.方法`的方式进行调用 静态方法在定义时,需要使用`staticmethod`装饰器,静态方法在定义时**不会传任何的默认参数**。 - 定义静态方法 ```python class Demo(object): @staticmethod def static_method(): print('11111111') ``` - 调用静态方法 ```python ... Demo.static_method() # output: 11111111 ``` ## 方法小结 | 类别 | 默认参数 | 调用方式 | | - | - | - | | 实例方法 | 把**类的实例**作为第一个实参(self) | 实例.方法 | | 类方法 | 把**类自己**作为第一个实参(cls) | 类.方法 | | 静态方法 | 无默认参数 | 类.方法 | 接着,再来对比一下`类方法`和`静态方法` **举例:** 我们定义两个父类,它们的`enter函数`分别是`类方法`和`静态方法` ```python class BaseRobot1(object): def __init__(self): # 机甲名 self.name = "危险流浪者" # 机甲版本 self.version = 3.0 @classmethod def enter(cls, user): """ 进入机甲方法 """ # 构建机甲实例 robot = cls() print(f"{user}已进入{robot.name},当前版本{robot.version}") ``` ```python class BaseRobot2(object): def __init__(self): # 机甲名 self.name = "危险流浪者" # 机甲版本 self.version = 3.0 @staticmethod def enter(user): """ 进入机甲方法 """ # 构建机甲实例 robot = BaseRobot() print(f"{user}已进入{robot.name},当前版本{robot.version}") ``` 调用它们的`enter`方法,查看结果 ```python BaseRobot1.enter() # xxx已进入危险流浪者,当前版本3.0 BaseRobot2.enter() # xxx已进入危险流浪者,当前版本3.0 ``` 结果都是一样的,在`enter`它们都构建了实例,一个是通过`cls`,另一个是通过`BaseRobot` 现在来继承这两个父类,为机甲升级版本 ```python class Robot1(BaseRobot1): def __init__(self): super().__init__() self.version = 4.0 class Robot2(BaseRobot2): def __init__(self): super().__init__() self.version = 4.0 ``` 此时再来分别调用两者的`enter`方法 ```python Robot1.enter() # 类方法: xxx已进入危险流浪者,当前版本4.0 Robot2.enter() # 静态方法:xxx已进入危险流浪者,当前版本3.0 ``` 由此可知,类方法的`cls`一直表示的是**当前类本身**,与静态方法相比较它是动态变换的 Last modification:August 21st, 2020 at 10:24 am © 允许规范转载