目录
面向对象和面向过程的区别?
面向对象语言:Python、Java、C++、C#(都是现在主流的)
面向过程语言:C (目前只接触到这个)
区别:强调的主体不同。
面向对象强调的那个主体去执行任务(规定的某个任务只能有某个对象执行),主体是执行人。
面向过程强调的是任务的执行(该任务可以交给任意对象执行) 对象和方法没有绑定
面向对象中的类、对象、属性(一个对象也称为一个实例):
打个比方,可以定义一个公交车类,这个类包含车牌号、车品牌、司机信息等,这些信息叫做这个对象的属性。这个公交车类可以创建出多个公交车对象(比如车牌号为777、车品牌位比亚迪、公交车司机是路小飞的一辆公交车,这辆公交车就是一个对象(也称实例),车牌号、车品牌、司机等信息称之为该对象的属性) 。对象是一个具体的物体(比如人类是一个类,这个类里面有叫做路小飞的人、有叫做小红的人,路小飞、小红就是一个对象(实例);而他们的外貌特征则是其属性)
面向对象的三大特征有:封装性、继承性、多态性。
类主要有两个部分组成:
属性:事物特有描述信息,描述事物是什么?
方法:事物的能力,事物可以做什么?
属性和方法的具体定义和具体内容见:Python类中属性和方法的定义_小凳子怕秃头的博客-CSDN博客
新式类和经典类比较
两者最大的不同就是MRO方法解析不同
python2中有经典类(深度优先算法)和新式类之分,默认都是经典类,只有显式继承了object才是新式类
python3中都是新式类,采用C3算法
抽象基类和抽象方法
python中内置了模块abc(abstract base class)来模拟实现一个抽象类
使用@abstractmethod装饰器
抽象基类中的抽象方法必须在子类中重写,否则子类无法创建成功
抽象基类不能被实例化
# ABC继承abc抽象类
from abc import ABC, abstractmethod
class Animal(ABC):
""" 继承自ABC =>Animal抽象基类"""
@abstractmethod
def eat(self):
"""
通过@abstractmethod装饰器,抽象方法
在子类中一定要重写该方法
:return:
"""
pass
def drink(self):
print("我要喝水")
# 抽象基类不能直接被实例化
# TypeError: Can't instantiate abstract class Animal with abstract method eat
# a = Animal()
class Person1(Animal):
def eat(self):
print("Person1")
p1 = Person1()
p1.eat()
元类
什么是元类:就是创建类的类,因为一个类本身又是另一个类实例。
元类的作用:可以用来对创建的类做限制,对类做个性化设置
python中默认的元类是type,object类的元类也是
print(type(object)) # 可查看object的类型是type
定义类的两种方式:
方法一:不使用class关键字
# 使用type创建一个类
# 定义类中的属性和方法
age = 1
def init(self,name):
self.name = name
def eat(self):
pass
# 使用type创建一个类Animal
# 参数1 类的名字 --》str
# 参数2 base父类 --》tuple
# 参数3 类中的属性和方法 --》dict
Animal = type('Animal',(object,), {'__init__':init, 'eat':eat, 'age':1})
a = Animal("猫猫")
print(a)
print(type(a))
print(type(type(a)))
print(type(Animal))
D:\Python\python.exe D:/python上课代码/yttljcode/yttlj上课代码/面向对象/元类.py
<__main__.Animal object at 0x000002468A365FD0>
<class '__main__.Animal'>
<class 'type'>
<class 'type'>
方法二:使用class关键,这里就不作赘述了
如何编写一个元类?定义的类的父类是自己编写的元类
一个元类必须要有__new__方法,new方法是创建一个实例并返回这个实例,这里是创建一个实例类。
# 自定义元类
class Mytype(type):
# 创建类
# def __new__(cls, *args, **kwargs):
# print(cls,args,kwargs)
# # new方法是创建一个实例并返回这个实例,这里是创建一个实例类。
# return type.__new__(cls,*args, **kwargs)
def __new__(cls, name, bases, attrs):
# 创建的类中必须要有foo属性,否则失败
if 'foo' not in attrs:
raise ValueError
# 字典生成式 修改类的属性名字都是小写字母
attr = {i.lower(): attrs[i] for i in attrs.keys()}
# print(cls, name, bases, attrs)
# new方法是创建一个实例并返回这个实例,这里是创建一个实例类。
return type.__new__(cls, name, bases, attr)
# 对刚刚创建的类做一些初始化的操作
def __init__(self, name, bases, attrs): # *args,**kwargs表示可边长参数
print(self,name, bases, attrs)
# 子类重写了父类方法,就不会调用父类的方法,为防止父类的一些初始化终止,这里需要手动的调用父类的__init__
super().__init__(name, bases, attrs)
# 默认情况下,Pig的元类是type,由于指定了元类metaclass=Mytype
class Pig1(metaclass=Mytype):
foo =1
Fool =2
p1 = Pig1()
print(p1.fool)