一、基本的例子
''' 概念:类、对象、 封装(防止数据被随意修改,外部调用变得简单)、 继承(共同点在父类,不同点在子类)、 多态(子类重写父类方法,对不同类的对象发出相同的消息将会有不同的行为) ''' class Dog: nation = "JAPAN" def __init__(self, name): # 构造函数 self.name = name def sayhi(self): # 类的方法 print(self.name + ": " + "hello,i'm a dog..") def __del__(self): print("析构方法,删除对象的引用后执行。例如:del(对象)或者程序执行结束",注意引用计数为0时才执行此方法) d1 = Dog("Dog1") d2 = Dog("Dog2") d1.sayhi() # Dog1: hello,i'm a dog.. d2.sayhi() # Dog2: hello,i'm a dog.. print(d1.nation, d2.nation) # JAPAN JAPAN Dog.nation = "JP" # 通过类修改共有属性 print(d1.nation, d2.nation) # JP JP d1.nation = "CN" # 只修改某对象的共有属性 print(d1.nation, d2.nation) # CN JP Dog.nation = "MO" # 再通过类修改共有属性 print(d1.nation, d2.nation) # CN MO
''' 最基本的类就写完了, self是实例本身: d = Dog("Dog1") <==> d = Dog(d, "Dog1") 1、成员属性self.name=name 2、方法def sayhi这个方法也是共有的类的所有成员都用这个方法, 要用私有方法只能: def sayhi2(self): print("my sayhi") d1.sayhi = sayhi2 d1.sayhi(d1) 3、私有属性self.__name=name 内部可以访问,外部不能访问, 如果想外部只读取,可以定义def get__name(self):return self.__name 4、共有属性,在类里定义的变量nation。对象d.nation先找成员属性nation再找 共有属性nation。如果没有成员属性nation就取类的nation, 如果d.nation = 1这样就创建了类本身的成员属性nation, 跟共有属性nation没有关系。 5、类里的方法和共有属性只有一份。类的所有对象共用类里的方法,这样是为什么 类的方法必须要有self关键字,这样类的方法才知道是谁在调用 6、__del__(self)是类的析构方法。作用是清除对象的引用(当引用被清除那内存空间很快 也将被垃圾回收机制清除),引用为0时会运行,在程序结束后会运行,运行中可以手动del(对象) '''
二、继承的例子
''' 继承可以通过“继承”或“组合”实现 多重继承,多级继承 ''' class Person: def __init__(self, name, age): self.name = name self.age = age def talk(self): print("person is talking..") class BlackPerson(Person): def __init__(self, name, age, strength): super().__init__(name, age) # <==> Person.__init__(name, age) self.strength = strength def talk(self): print("Black Person talking..") class WritePerson(Person): pass b = BlackPerson("Smith", 30, "Strong") b.talk()
class SchoolMember: ''' 学校成员类 ''' member = 0 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def enroll(self): print("注册了一个新成员:", self.name) SchoolMember.member += 1 def tell(self): print("打印个人信息:",self.name) for k in self.__dict__: print(k,self.__dict__[k]) print("---------end------------") def __del__(self): print("开除了:",self.name) SchoolMember.member -= 1 class Teacher(SchoolMember): def __init__(self, name, age, sex, salary, course): super().__init__(name, age, sex) self.salary = salary self.course = course self.enroll() def teaching(self): print("teaching 课程:", self.course) class Student(SchoolMember): def __init__(self, name, age, sex, course, tuition): super().__init__(name, age, sex) self.course = course self.tuition = tuition self.amount = 0 self.enroll() def pay_tution(self, amount): print(self.name, amount) self.amount += amount t1 = Teacher("Wusir", 28, "M", 8000, "Python") s1 = Student("HaiTao", 20, "F", "python", 12000) s1 = Student("Jack", 20, "F", "python", 12000) # print(SchoolMember.member) # del(s1) s1.tell()
三、新式类经典类一丝丝区别(不重要)
################################################################################ 了解,不重要: Python2中,继承的层级。经典类是深度查询,新式类是广度查询 python3中,继承的层级。都是广度查询 ###############################################################################
四、Python模拟多态
''' 多态:接口重用 Python模拟多态 ''' class Animal: def __init__(self, name): self.name = name def talk(self): raise NotImplementedError("子类必须重构talk方法") @staticmethod def all_talk(obj): obj.talk() class Cat(Animal): def talk(self): print("Miao..Miao..") class Dog(Animal): def talk(self): print("Wang..Wang..") d = Dog("dog1") c = Cat("cat1") Animal.all_talk(d) Animal.all_talk(c)
五、类的属性有哪些
############################################################################## ''' 属性: 成员属性 公有属性(类属性) 私有属性 方法: 公有方法 私有方法 静态方法@staticmethod 类方法@classmethod
属性方法(特性)@property ''' ###############################################################################
六、静态方法例子
''' 静态方法@staticmethod 静态方法相当于单纯的函数,没有self关键字 类方法@classmethod 类方法只能访问公有属性。之前每个对象修改的公有属性是自己的, 通过类修改公有属性才改的大家的。 变为类方法后任何对象都可以修改公有属性。 ''' class Person: nation = "朝鲜" def __init__(self, name): self.name = name @classmethod def change_nation(self): self.nation = "中国" p = Person("金三胖") p1 = Person("朴xx") p.change_nation() print(p.nation, p1.nation) #中国 中国 print(Person.nation) #中国
七、属性方法(或者叫做特性)
class Dog: def __init__(self): self.__food = None @property def eat(self): print("eat:", self.__food) @eat.setter def eat(self, food): self.__food = food @eat.deleter def eat(self): del self.__food d = Dog() d.eat d.eat = "骨头" d.eat del d.eat d.eat ############ # eat: None # eat: 骨头 # AttributeError: 'Dog' object has no attribute '_Dog__food' ############
''' 属性方法的应用实例: 用户查航班状态, 1、需要调航空公司接口 2、解析数据 3、返回给用户结果 ''' class Flight: def __init__(self, name): self.name = name @property def flight_status(self): api = 1 if api == 0: print("航班延迟") elif api == 1: print("航班到达") elif api == 2: print("航班飞走") else: print("无法确认") f = Flight("CA980") f.flight_status
八、理解概念“类也是一个对象”
''' __doc__:打印类的注释信息 __module__:返回对象的模块 __class__:输出类名 __init__: __del__: __call__:让对象可以加括号运行 __dict__:查看类(打印类里的所有属性不包括实例属性)或对象(打印实例属性不包括类属性)中的所有成员 __str__:打印对象的字符串形式 __getitem__:用户自己封装一个字典,用字典的形式使用对象,obj["name"] __setitem__:用户自己封装一个字典,用字典的形式使用对象,obj["name"]="alex" __delitem__:用户自己封装一个字典,用字典的形式使用对象,del obj["name"] __metaclass__:定义自己的类被哪个原类创建 ''' ''' 类也是一个对象。类的类是type ''' def func(self): print("hello world", self.name, self.age) def __init__(self, name, age): self.name = name self.age = age Foo = type("Foo", (), {"talk":func, "__init__":__init__}) # 类定义(用type实例化类) f = Foo("BB", 23) # 实例化对象 f.talk() # 打印hello world
九、对象怎么被创建的? 1.先由“元类” 创建“元类”的对象--“类” 2. 再由“类” 创建“类”的对象--“对象”
class MyType(type): def __init__(self, what, bases=None, dict=None): print("---MyType init---") super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): print("---MyType call---") obj = self.__new__(self, *args, **kwargs) self.__init__(obj, *args, **kwargs) class Foo: __metaclass__ = MyType # Python2中:对象类Foo被MyType元类创建 def __new__(cls, *args, **kwargs): print("Foo __new__") return object.__new__(cls) # cls是对象类本身__new__在__init__之前执行,创建实例要用 def __init__(self, name): self.name = name print("Foo __init__") f = Foo("Tommy") ####----Python2中的输出结果: # ---MyType init--- # ---MyType call--- # Foo __new__ # Foo __init__ ############################# ####----Python3中的输出结果: # Foo __new__ # Foo __init__ #############################
如果要在Python3中想要获得Python2中的输出结果:
class MyType(type): def __init__(self, what, bases=None, dict=None): print("---MyType init---") super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): print("---MyType call---") obj = self.__new__(self, *args, **kwargs) self.__init__(obj, *args, **kwargs) class Foo(metaclass=MyType): # Python3中:对象类Foo被MyType元类创建 def __new__(cls, *args, **kwargs): print("Foo __new__") return object.__new__(cls) # cls是对象类本身__new__在__init__之前执行,创建实例要用 def __init__(self, name): self.name = name print("Foo __init__") f = Foo("Tommy") ####----Python2中的输出结果:未使用 # ############################# ####----Python3中的输出结果: # ---MyType init--- # ---MyType call--- # Foo __new__ # Foo __init__ #############################
元类是如何创建的?
class UpperAttrMetaClass(type): def __new__(mcs, class_name, class_parents, class_attr): print("---UpperAttrMetaClass new---") # attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__')) # class_attr = dict((name.upper(), value) for name, value in attrs) a = super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, class_parents, class_attr) return a # <class '__main__.UpperAttrMetaClass'> def __init__(cls, *args, **kwargs): print("---UpperAttrMetaClass init---") super(UpperAttrMetaClass, cls).__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): print("---UpperAttrMetaClass call---") obj = cls.__new__(cls, *args, **kwargs) cls.__init__(obj, *args, **kwargs) class Foo(metaclass=UpperAttrMetaClass): bar = 12 money = 'unlimited' def __new__(cls, *args, **kwargs): print("Foo __new__") return object.__new__(cls) # cls是对象类本身__new__在__init__之前执行,创建实例要用 def __init__(self, name): self.name = name print("Foo __init__") Foo('alex') print('Foo.bar:', Foo.bar) print('Foo.money:', Foo.money) ######################## # ---UpperAttrMetaClass new--- # ---UpperAttrMetaClass init--- # ---UpperAttrMetaClass call--- # Foo __new__ # Foo __init__ # Foo.bar: 12 # Foo.money: unlimited ########################
完整
class MyMetaClass(type): def __new__(mcs, name, bases, attrs): ''' 作用是创建一个类Foo, :param name: 类名 :param bases: 父类 :param attrs: 类的属性、方法 :return: ''' print('---1.MyMetaClass.__new__: 参数为(类名,父类,类的属性或方法),创建一个Foo类,并给Foo类加一个属性"hh"---') attrs['hh'] = 'haha' # 用这里返回的Foo调用__call__方法来创建Foo对象,如果不返回,下面的__call__会调用失败 return super(MyMetaClass, mcs).__new__(mcs, name, bases, attrs) def __init__(cls, name, bases=None, attrs=None): print( '---2.MyMetaClass.__init__: Foo类已经创建好了,走到__init__里面了,这里面只是用于创建完了做一点事情 ' ' 不调用父类__init__没关系,没有返回值也没关系,估计这个方法没什么用---') def __call__(cls, *args, **kwargs): ''' 这个方法是对子类的Foo.__new__()方法进行拦截。子类Foo创建的对象都是这个方法的返回值。 如果不返回,子类Foo创建的对象都为None 等价于:Foo(*args, **kwargs) ''' print("---3.MyMetaClass.__call__: 用于创建Foo类的实例,如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2} " " 这个方法在Foo.__new__之前执行,Foo类的实例优先为这个方法的返回值,其次为Foo.__new__的返回值 " " 必须调Foo的new和init方法。如果不调用Foo.__new__对象为None,不调用Foo.__init__对象没被初始化") print(cls) obj = cls.__new__(cls, *args, **kwargs) cls.__init__(obj, *args, **kwargs) return obj class Bar: def __new__(cls, *args, **kwargs): print('Bar __new__') return object.__new__(cls) class Bar1: def __new__(cls, *args, **kwargs): print('Bar1 __new__') return object.__new__(cls) class Foo(metaclass=MyMetaClass): # metaclass只是用来创建Foo用,__new__方法是创建Foo的实例用,优先用自己的__new__,其次用第一个父类的__new__ def __new__(cls, *args, **kwargs): # 如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2} print('---4.Foo.__new__:返回Foo的未初始化的实例---') return object.__new__(cls) # cls是对象类本身,只接收一个参数 def __init__(self, name): self.name = name print("---5.Foo.__init__---") f = Foo('alex') print(f.name) print(Foo.hh) ''' ---1.MyMetaClass.__new__: 参数为(类名,父类,类的属性或方法),创建一个Foo类,并给Foo类加一个属性"hh"--- ---2.MyMetaClass.__init__: Foo类已经创建好了,走到__init__里面了,这里面只是用于创建完了做一点事情 不调用父类__init__没关系,没有返回值也没关系,估计这个方法没什么用--- ---3.MyMetaClass.__call__: 用于创建Foo类的实例,如果Foo(12, k=1, p=2), 这里的args=(12,) kwargs={'k':1, 'p':2} 这个方法在Foo.__new__之前执行,Foo类的实例优先为这个方法的返回值,其次为Foo.__new__的返回值 必须调Foo的new和init方法。如果不调用Foo.__new__对象为None,不调用Foo.__init__对象没被初始化 <class '__main__.Foo'> ---4.Foo.__new__:返回Foo的未初始化的实例--- ---5.Foo.__init__--- alex haha '''
重要:metaclass也从父类继承
假设用户定义一个class User(Model)
时,Python解释器首先在当前类User
的定义中查找__metaclass__
,
如果没有找到,就继续在父类Model
中查找__metaclass__
,找到了,就使用Model
中定义的__metaclass__
的ModelMetaclass
来创建User
类,
也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。
用metaclass实现ORM框架:https://www.liaoxuefeng.com/wiki/897692888725344/923030550637312
思考,如果有动态创建表的需求,如银行小微系统根据指标大类动态创建表,需要使用type()来动态创建类。这样动态创建的类才能使用ORM框架
general_table = type(类名,父类, 属性) //创建model类
general_table.create() //动态创建表
创建过程图示: