参考链接:【Python】零基础入门——面向对象编程(强烈推荐)_哔哩哔哩_bilibili
python面向对象的方法种类
python面向对象中的方法的种类有:
划分的依据是:方法的第一个参数必须要接受的数据类型。
同时不管是哪一种类型的方法,都是存储在类当中;没有在实例对象当中。
不同类型方法的调度方式会不同。
- 实例方法:默认第一个参数需要接收到一个实例
- 类方法:默认第一个参数需要接收到一个类
- 静态方法:第一个参数任意,没有默认接收
class Student: # 实例方法 def study(self): print("I am learning",self) pass # 类方法 @classmethod def classmate(cls): print("这是一个同班同学类",cls) pass # 静态方法 @staticmethod def grow_up(): print("这是一个静态方法") pass
方法的不同作用
在三种方法之间的不同用途和区别:
-
在实例方法中,首先最需要注意的就是,self其实就是这个实例对象本身,也就是说是这个对象的地址(ID号),这个在调用方法或者输出对象,在最后的地址可以验证。同时self这个形参并不是一定要叫self,可以随便取名字,但规范上要求写成self。虽然是自动传,所以self这个参数必须写,实例方法一般在使用实例的时候能够很好的调用,不需要传参数,直接对象点击就传过去
-
在类方法中,首先最需要注意的就是,cls表示的是这个类本身,也就是说这个用类来调用的方法,同时类方法也是只需要用到类的时候进行调用
-
静态方法则就是不需要用到类和对象实例的时候进行使用,较为方便
方法的存储
在老师的研究下表明,这些方法无论是实例方法、类方法还是静态方法, 一开始在对象里面都是不存在的,都保存在了类里面,这个从类的dict属性中可以看到,代码如下:
class Student: # 实例方法 def study(self): print("I am learning",self) pass # 类方法 @classmethod def classmate(cls): print("这是一个同班同学类",cls) pass # 静态方法 @staticmethod def grow_up(): print("这是一个静态方法") pass pass ZhangSan = Student() # 这里会输出为空 print(ZhangSan.__dict__) # 这里会输出为键值对。,可以发现方法存储在类里面 print(Student.__dict__)
方法的调用方式
-
实例方法的标准调用方式与其他调用方式,方法见下面例子
class Student: # 实例方法 def study(self,subject): print("I am learning",subject) pass # 类方法 驱动注解(视频中称之为装饰器) @classmethod def classmate(cls): print("这是一个同班同学类",cls) pass # 静态方法 @staticmethod def grow_up(): print("这是一个静态方法") pass pass ZhangSan = Student() # 实例方法标准调用方式,不需要写第一个形参 ZhangSan.study("math") # 实例方法其他调用:直接找到函数本身进行调用,例如 Student.study(ZhangSan,"math") # 或者如下: func = Student.study func(ZhangSan,"math") # 类方法调用方式:首先如果你直接使用类名进行调用,那OK没有问题,如果你使用类的是实例对象进行调用, # 那么python会自动找到其中对象所对应的类,传过来进行调用,类方法与C++ Java中的静态方法是不一样的 # 注解的作用是:在保证原有函数的功能不改变情况下,增加函数的功能(偏底层的功能) Student.classmate() ZhangSan.classmate() # 会直接把对象的类传过去 # 甚至如下方式也可以 func = Student.classmate() func(Student) # 甚至可以这样去使用,但这样的话,就有点违背开发者的意志了 class S: pass S.study() # 这里输出的类名是S # 静态方法的调用方式:其不需要接收第一个默认参数,既可以通过类进行调用,也可以通过实例来进行调用 Student.classmate()
ZhangSan.classmate()
或者如下这种方式:func = Student.classmate()
func(Student)
**不同的方法访问不同的属性的规律** 这里其实讲过了,因为实例对象是可以访问类对象的属性,但类不可以,原因是对象保存了类对象的地址,但类是访问不到对象的属性的,因为类没有保存每一个实例对象的地址,所以对于实例方法而言,实例方法会访问到 ```python class Student: age = 0 # 实例方法 def study(self): print(self.age) print(self.num) pass # 类方法 驱动注解(视频中称之为装饰器) @classmethod def classmate(cls): print(self.age) print(self.num) pass # 静态方法 @staticmethod def grow_up(): print(self.age) print(self.num) pass pass ZhangSan = Student() ZhangSan.num = 10 # 下面可以成功运行 ZhangSan.study() # 下面运行报错,表示没有num属性 ZhangSan.classsmate() # 所以因此静态方法也是访问不到的
元类
创建类对象的类,就是个元类。值得一说的是python里面数据类型全部都是对象
num = 10 print(num__class__) print(num.__class__.__class__) # 输出元类type type是最大的那个元类
类对象的创建方式
# 上面写了什么叫做元类,那我们这里就要开始创建类对象 num = 10 # 打印出num对象的类名称 print(type(num)) # 除此之外type还可以创建类对象,例如下面我可以创建一个Student的对象,其中第二个参数(元组)表示的是Student的父类是什么,第三个参数表示的dict属性,可以添加属性和方法,返回回去的变量ZhangSan,原视频中使用的函数名当地址 ZhangSan = type("Student",(),{“age”: 18,"study": 地址})
元类的查找机制
# 在python当中可以通过__metaclass__来赋予一个元类 # 例如 class Student: __metaclass__ = Proson pass # 或者 class Student(metaclass = Proson): __metaclass__ = Proson pass # 而类在创建过程中,首先是从自己__metaclass__里面去找,如果自己没有,则先去父类里面去找,然后到父类里面的__metaclass__去找,如果父类里面也没有,就会直接去文件模块里面找,一般来说模块里面会标注出__metaclass__是xxx 这样通过继承可以控制所有类的对象的元类,模块也是... # 元类的应用场景: # 1. 拦截类的创建 # 2. 修改类 # 3. 返回修改之后的类 # 4. 后面补充
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)