Python面向对象

Eecho
Eecho
发布于 2024-12-25 / 245 阅读
24
0

Python面向对象


面向对象

对象就是“容器”,用来存放数据和功能的,数据和功能的集合体

类也是“容器”,是用来存放同类对象共同的数据和功能的

# 英雄的数据
# hero_name = '鲁班七号'
# hero_speed = 450
# hero_hp = 3000
# hero_atk = 100
​
​
# 英雄的功能
def get_hero_info(hero_obj):
    print(f'英雄属性:名字{hero_obj["hero_name"]} 移速:{hero_obj["hero_speed"]}'
          f'生命值:{hero_obj["hero_hp"]} 攻击力:{hero_obj["hero_atk"]}')
​
def set_hero_speen(hero_obj,speed_plus):
    hero_obj['hero_speed'] += speed_plus
​
#玩家的数据
user_name = '张大仙'
user_gender = 'famale'
user_team = 'XYG'
user_dan = '王者荣耀'
​
#玩家的功能
def get_user_info():
    print(f'玩家属性:名字{user_name} 性别:{user_gender}'
          f'战队:{user_team} 段位:{user_dan}' )
​
def set_user_name(name):
    global user_name
    user_name = name
​
​
​
​
hero_obj = {
    'hero_work':'射手',
    'hero_name':'鲁班七号',
    'hero_speed':450,
    'hero_hp':3000,
    'hero_atk':100,
    'get_hero_info': get_user_info,
    'set_hero_speed': set_hero_speen
}
​
​
hero1_obj = {
    'hero_work': '射手',
    'hero_name':'后羿',
    'hero_speed':460,
    'hero_hp':3100,
    'hero_atk':110,
    'get_hero_info': get_hero_info,
    'set_hero_speed': set_hero_speen
}
​
​

归类

解决不同对象存相同数据的问题

类的名字空间实在定义阶段就产生了

​
class Hero:
    hero_work = '射手'
    def get_hero_info(hero_obj):
        print(f'英雄属性:名字{hero_obj["hero_name"]} 移速:{hero_obj["hero_speed"]}'
              f'生命值:{hero_obj["hero_hp"]} 攻击力:{hero_obj["hero_atk"]}')
​
    def set_hero_speen(hero_obj,speed_plus):
        hero_obj['hero_speed'] += speed_plus
​
    print('xxx')
​
# 属性访问
print(Hero.__dict__)
print(Hero.__dict__['get_hero_info'])
print(Hero.hero_work)
​
hero_obj1 = Hero()
hero_obj2 = Hero()
hero_obj3 = Hero()
print(hero_obj1.__dict__)
print(hero_obj2.__dict__)
print(hero_obj3.__dict__)
​
print(hero_obj1.hero_work)
​
# hero_obj1.__dict__['name'] = '鲁班七号'
# hero_obj1.__dict__['speed'] = 450
# hero_obj1.__dict__['hp'] = 3000
# hero_obj1.__dict__['atk'] = 100
# print(hero_obj1.__dict__)
​
hero_obj1.name = '鲁班七号'
hero_obj1.speed = 450
hero_obj1.hp = 3000
hero_obj1.atk = 100
print(hero_obj1.__dict__)

init

hero_obj1 = Hero()
hero_obj2 = Hero()
hero_obj3 = Hero()
​
def init(hero_obj, name, speed, hp, atk):
    hero_obj.name = name
    hero_obj.speed = speed
    hero_obj.hp = hp
    hero_obj.atk = atk
    print(hero_obj.__dict__)
    print(hero_obj.hero_work)
​
init(hero_obj1, '鲁班七号', 450, 3000, 100 )
init(hero_obj2, '后羿', 460, 3100, 110 )
init(hero_obj3, '虞姬', 470, 3200, 120 )
​
print(hero_obj1.__dict__)
print(hero_obj2.__dict__)
print(hero_obj3.__dict__)

class Hero:
    hero_work = '射手'
​
    def __init__(hero_obj, name, speed, hp, atk):
        hero_obj.name = name
        hero_obj.speed = speed
        hero_obj.hp = hp
        hero_obj.atk = atk
        print(hero_obj.__dict__)
        print(hero_obj.hero_work)
​
    def get_hero_info(hero_obj):
        print(f'英雄属性:名字{hero_obj["hero_name"]} 移速:{hero_obj["hero_speed"]}'
              f'生命值:{hero_obj["hero_hp"]} 攻击力:{hero_obj["hero_atk"]}')
​
    def set_hero_speen(hero_obj,speed_plus):
        hero_obj['hero_speed'] += speed_plus
​
    print('xxx')
​
# 实例化
hero1_obj = Hero('鲁班七号', 450, 3000, 100)    # Hero.__init__(空对象,)

调用类的过程
1、创建空对象
2、调用__init__方法,同时把空对象,以及调用类的时候括号里传的参数,一同传递给__init__方法
3、返回初始化之后的对象

属性查找顺序

对象自己没有,才会去类里面查找

# 实例化
hero1_obj = Hero('鲁班七号', 450, 3000, 100)    # Hero.__init__(空对象,)
hero2_obj = Hero('后羿', 460, 3100, 110 )
hero3_obj = Hero('虞姬', 470, 3200, 120 )
​
# print(hero1_obj.name)
print(hero1_obj.hero_work)
print(hero2_obj.hero_work)
print(hero3_obj.hero_work)
​
print(id(hero1_obj.hero_work))
print(id(hero2_obj.hero_work))
print(id(hero3_obj.hero_work))

数据属性的特点

class Hero:
    hero_work = '射手'
    count = 0
​
    def __init__(hero_obj, name, speed, hp, atk):
        hero_obj.name = name
        hero_obj.speed = speed
        hero_obj.hp = hp
        hero_obj.atk = atk
        Hero.count += 1
​
​
    def get_hero_info(hero_obj):
        print(f'英雄属性:名字{hero_obj["hero_name"]} 移速:{hero_obj["hero_speed"]}'
              f'生命值:{hero_obj["hero_hp"]} 攻击力:{hero_obj["hero_atk"]}')
​
    def set_hero_speen(hero_obj,speed_plus):
        hero_obj['hero_speed'] += speed_plus
​
    print('xxx')
​
​
hero1_obj = Hero('鲁班七号', 450, 3000, 100)    # Hero.__init__(空对象,)
hero2_obj = Hero('后羿', 460, 3100, 110 )
hero3_obj = Hero('虞姬', 470, 3200, 120 )
print(Hero.count)

隐藏属性

封装:整合

隐藏属性

1、隐藏的本质,知识一种改名操作

2、对外不对内

3、改名操作,只会在类的定义阶段检查子代码语法的时候执行一次,之后定义的__开头的属性都不会改名

1、隐藏的本质,知识一种改名操作

class Test:
    x = 10
    def f1(self):
        print('f1')
​
print(Test.x)
print(Test.f1)
​
#运行结果
#10
#<function Test.f1 at 0x00000190BF6790D8>
class Test:
    __x = 10
    def __f1(self):
        print('f1')

obj = Test()
print(obj.__x)
print(obj.__f1)
print(Test.x)
print(Test.f1)

#运行结果
#Traceback (most recent call last):
#  File "C:\Users\4C69\PycharmProjects\python_basics\小飞\进阶篇\01-面向对象介绍.py", line 196, in <module>
#    print(obj.__x)
#AttributeError: 'Test' object has no attribute '__x'
class Test:
    __x = 10
    def __f1(self):
        print('f1')

obj = Test()
print(Test.__dict__)
print(obj._Test__x)
print(Test._Test__x)

#{'__module__': '__main__', '_Test__x': 10, '_Test__f1': <function Test.__f1 at 0x000001BFDAC690D8>, #'__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' #objects>, '__doc__': None}
#10
#10

2、对外不对内

class Test:
    __x = 10
    def __f1(self):
        print('f1')
    def f2(self):
        print(self.__x)
        print(self.__f1)


obj = Test()
obj.f2()

#运行结果
#10
#<bound method Test.__f1 of <__main__.Test object at 0x0000018576CDF188>>

3、改名操作,只会在类的定义阶段检查子代码语法的时候执行一次,之后定义的__开头的属性都不会改名

class Test:
    __x = 10
    def __f1(self):
        print('f1')
    def f2(self):
        print(self.__x)
        print(self.__f1)

Test.__y = 20
print(Test.__dict__)

# 运行结果
#{'__module__': '__main__', '_Test__x': 10, '_Test__f1': <function Test.__f1 at 0x0000015FA6689168>, 'f2': ##<function Test.f2 at 0x0000015FA6692798>, '__dict__': <attribute '__dict__' of 'Test' objects>, #'__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, '__y': 20}

property

class Test:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_name(self):
        return self.__name
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self, new_age):
        if type(new_age) is not int:
            print('你个傻子,必须传整型!')
            return
        if not 0 <= new_age <= 150:
            print('你个傻子,年龄必须在0-150岁!')
        self.__age = new_age
    @age.deleter
    def age(self):
        del self.__age

obj = Test('xxx', 18)
print(obj.age)
obj.age = 5
print(obj.age)


#运行结果
#18
#5

继承

继承:创建新类的方式,通过继承创建的类称为子类,被继承的类称之为父类(基类)

# 在Python2里面,有新式类和经典类的区分
# 新式类:继承了object类的子类,以及继承了这个子类的子子孙孙类
# 经典类:没有继承object类的子类,以及继承了这个子类的子子孙孙类


# 继承的特性:遗传

# 多继承
# 优点:一个子类可以同时遗传多个父类的属性
# 缺点
    # 1、多继承违背了人的思维习惯
    # 2、多继承会让代码的可读性变差
# 如果必须用多继承,应该用Mixins


# 属性查找
对象-类-父类-……object

class Human:
    star = 'earth'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Chinese(Human):
    nation = 'China'

    # def __init__(self, name, age, gender):
    #     self.name = name
    #     self.age = age
    #     self.gender = gender

    def speak_chinese(self):
        print(f'{self.name}在说普通话')


class American(Human):
    nation = 'America'

    # def __init__(self, name, age, gender):
    #     self.name = name
    #     self.age = age
    #     self.gender = gender

    def speak_english(self):
        print(f'{self.name}在说英语')


dy_obj = Chinese('董永', 18, '男')
print(dy_obj.__dict__)
print(dy_obj.nation)
print(dy_obj.star)
dy_obj.speak_chinese()

# 运行结果
#{'name': '董永', 'age': 18, 'gender': '男'}
#China
#earth
#董永在说普通话

class Human:
    star = 'earth'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class Chinese(Human):
    nation = 'China'

    def __init__(self, name, age, gender, balance):
        Human.__init__(self, name, age, gender)
        self.balance = balance

    def speak_chinese(self):
        print(f'{self.name}在说普通话')


class American(Human):
    nation = 'America'

    # def __init__(self, name, age, gender):
    #     self.name = name
    #     self.age = age
    #     self.gender = gender

    def speak_english(self):
        print(f'{self.name}在说英语')


dy_obj = Chinese('董永', 18, '男')
print(dy_obj.__dict__)
print(dy_obj.nation)
print(dy_obj.star)
dy_obj.speak_chinese()


# 运行结果
#{'name': '董永', 'age': 18, 'gender': '男', 'balance': 2000}
#China
#earth
#董永在说普通话

单继承查找

class Test1:
    def f1(self):
        print('Test1.f1')

    def f2(self):
        print('Test1.f2')
        self.f1()


class Test2(Test1):
    def f1(self):
        print('Test2.f1')


obj = Test2()
obj.f2()


# 运行结果
#Test1.f2
#Test2.f1

多继承属性查找

菱形问题(钻石问题)

MRO列表,C3算法实现

class A:
    def f1(self):
        print('A.f1')


class B(A):
    def f1(self):
        print('B.f1')


class C(A):
    def f1(self):
        print('C.f1')


class D(B,A):
    def f2(self):
        print('D.f2')


obj = D()
obj.f1()
print(D.mro())

# 运行结果
#B.f1
#[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

非菱形查找


class A:
    def f1(self):
        print('A.f1')


class B:
    def f1(self):
        print('B.f1')


class C(A):
    def f1(self):
        print('C.f1')


class D(B):
    def f1(self):
        print('D.f1')


class E:
    def f1(self):
        print('E.f1')


class F(C, D, E):
    def f2(self):
        print('F2')


print(F.mro())
obj = F()
obj.f1()

# 运行结果
#[<class '__main__.F'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class #'__main__.B'>, <class '__main__.E'>, <class 'object'>]
#C.f1

深度优先查找

广度优先查找

# 菱形继承
# 经典类:深度优先查找,找第一条分支的时候,就要找共同的父类
# 新式类:广度优先查找,找完最后一条分支之后,才找共同的父类
class Z:
    def f1(self):
        print('Z.f1')


class A(Z):
    def f2(self):
        print('A.f1')


class B(Z):
    def f2(self):
        print('B.f1')


class C(A):
    def f2(self):
        print('C.f1')


class D(B):
    def f2(self):
        print('D.f1')


class E(Z):
    def f2(self):
        print('E.f1')


class F(C, D, E):
    def f2(self):
        print('F.f2')


print(F.mro())

obj = F()
obj.f1()


# 运行结果
#[<class '__main__.F'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class #'__main__.B'>, <class '__main__.E'>, <class '__main__.Z'>, <class 'object'>]
#Z.f1

Mixins

注意:

1、继承结构不要太复杂

2、满足什么“是"什么的关系(is-a)

MixIns机制

class Fowl:    #家禽类
    pass


class SwimMixIn:
    def swimming(self):
        pass


class Chicken(Fowl):    #鸡
    pass


class Duck(SwimMixIn, Fowl):
    pass


class Goose(SwimMixIn, Fowl):     #鹅
    pass

super

super是参照对象所属类的mro列表, 从mro列表里super所处的类的下一个类开始找

class Human:
    star = 'earth'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Chinese(Human):
    nation = 'China'

    def __init__(self, name, age, gender, balance):
        # Human.__init__(self, name, age, gender)
        # super(Chinese, self).__init__(name, age, gender)   #python2写法
        super().__init__(name, age, gender)                  #python3写法
        self.balance = balance

    def speak_chinese(self):
        print(f'{self.name}在说普通话')


obj = Chinese('大仙', 18, 'female', 2500)
print(Chinese.mro())
print(obj.__dict__)


# 运行结果
#[<class '__main__.Chinese'>, <class '__main__.Human'>, <class 'object'>]
#{'name': '大仙', 'age': 18, 'gender': 'female', 'balance': 2500}

多态


    def run(self):
        print('开始跑', end=' ')

class Benz(Car):
    def run(self):
        super().run()
        print('加98号汽油')

class Lx(Car):
    def run(self):
        super().run()
        print('充电')

class Auto(Car):
    def run(self):
        super().run()
        print('加92号汽油')

car1 = Benz()
car2 = Lx()
car3 = Auto()
car1.run()
car2.run()
car3.run()

def drive_car(car):
    car.run()

drive_car(car1)
drive_car(car2)
drive_car(car3)


# 运行结果
#开始跑 加98号汽油
#开始跑 充电
#开始跑 加92号汽油
#开始跑 加98号汽油
#开始跑 充电
#开始跑 加92号汽油

抽象基类

抽象基类它提供了接口,但是又没有去把接口实现的类,需要由子类完成。

import abc

class Car(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def run(self):
        pass


class Benz(Car):
    def run(self):
        pass

class Lx(Car):
    def run(self):
        pass

class Auto(Car):
    def run(self):
        pass

car1 = Benz()
car2 = Lx()
car3 = Auto()
car1.run()
car2.run()
car3.run()

类方法

settings.py

IP = '127.0.0.1'
PORT = 3306

import settings
class Mysql:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def f1(self):
        print(self.ip, self.port)

    @classmethod
    def instance_from_conf(cls):
        print(cls)
        obj = cls(settings.IP, settings.PORT)
        return obj


obj = Mysql.instance_from_conf()
print(obj.__dict__)



# 运行结果
#<class '__main__.Mysql'>
#{'ip': '192.168.1.8', 'port': '3306'}

静态方法

class Mysql:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def f1(self):
        print(self.ip, self.port)

    @staticmethod
    def f2():
        print('嘿嘿嘿')



Mysql.f2()


# 运行结果
#嘿嘿嘿

反射机制

hasattr() :判断该对象是否有指定名字的属性或方法,返回值是bool类型

getattr() :获取对象指定名称的属性或方法,返回值是str类型

setattr() :给指定的对象添加属性以及属性值

delattr() :删除对象指定名称的属性或方法值,无返回值

class Ftp:
    def put(self):
        print('正在长传数据。。。')

    def get(self):
        print('正在下载数据。。。')

    def interact(self):
        opt = input('>>>')
        # if hasattr(self, opt):
        #     getattr(self, opt)()
        # else:
        #     print('功能不存在')
        getattr(self, opt, self.warning)()

    def warning(self):
        print('功能不存在')


obj = Ftp()
obj.interact()

obj2 = Ftp()
obj2.interact()

# 运行结果
#>>>xxx
#功能不存在
#>>>get
#正在下载数据。。。

内置方法

开头 结尾的

会在满足条件的时候自动执行

如:__ init __

str

class Human:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        print('__str__运行了')
        return '嘿嘿嘿'


obj = Human('张大仙', 73)
print(obj)

# 运行结果
#__str__运行了
#嘿嘿嘿

del

在删除对象的时候,先执行

class Human:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __del__(self):
        print('__del__运行了。。。')

obj = Human('张大仙', 73)
# print(obj)
print('='*20)


obj2 = Human('李白', 80)
del obj2
print('*'*20)

# 运行结果
#====================
#__del__运行了。。。
#********************
#__del__运行了。。。

元类

实例化产生类的类

元类 -- 实例化 -- 类 -- 实例化 -- 对象

用class这个关键字,定义的所有的类,以及内置的类,都是由内置的元类type,实例化产生的。

# 1、类名
class_name = 'Human'

# 2、基类
class_bases = (object,)


# 3、执行类子代码,产生名称空间
class_dic = {}
class_body = '''
def __init__(self, name, age):
        self.name = name
        self.age = age
def info(self):
    print('name:', self.name, 'age:', self.age)
'''

exec(class_body, {}, class_dic)
print(class_dic)

# 4、调用元类
Human = type(class_name, class_bases, class_dic)
print(Human)
obj = Human('张大仙', 73)
obj.info()

# 运行结果
#{'__init__': <function __init__ at #0x0000015AA88490D8>, 'info': <function info at #0x0000015AA8849168>}
#<class '__main__.Human'>
#name: 张大仙 age: 73

自定义元类

class Mytype(type):
    def __init__(self, class_name, class_bases, class_dic):
        print('Mytype.init')
        print(self)
        print(class_name)
        print(class_bases)
        print(class_dic)
        if '_' in class_name:
            raise NameError('类名不能有下划线')
        if not class_dic.get('__doc__'):
            raise SyntaxError('定义类必须写注释!')

            
# Human = Mytype(class_name, class_bases, class_dic)
# 1、调用Mytype的__new__方法,产生一个空对象Human
# 2、调用Mytype的init方法,初始化对象Human
# 3、返回初始化好的对象Human
            
    
class Human(metaclass=Mytype):
    """
    aaa
    """
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
        
# 运行结果        
#Mytype.init
#<class '__main__.Human'>
#Human
#()
#{'__module__': '__main__', '__qualname__': 'Human', #'__doc__': '\n    aaa\n    ', '__init__': <function #Human.__init__ at 0x000001B3E5992318>}

new

class Mytype(type):
    def __init__(self, class_name, class_bases, class_dic):
        print('Mytype.init')
        # print(class_name)
        # print(class_bases)
        # print(class_dic)
        # print(self.__base__)
        # print(type(self))
    def __new__(cls, *args, **kwargs):
        print('Mytype.__new__')
        # print(cls)
        # print(args)
        return super().__new__(cls, *args, **kwargs)

class Human(object, metaclass=Mytype):
    """
    aaa
    """
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
        
# 结果
# Mytype.__new__
# Mytype.init

call

# 自定义元类
class Mytype(type):
    def __call__(self, *args, **kwargs):
        human_obj = self.__new__(self)
        self.__init__(human_obj, *args, **kwargs)
        dic = {}
        for key in human_obj.__dict__:
            dic[f'H_{key}'] = human_obj.__dict__[key]

        human_obj.__dict__ = dic
        return human_obj

class Human(metaclass=Mytype):
    '''
    测试元类,嘿嘿嘿~
    '''
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def info(self):
        print('name:', self.name, 'age:', self.age)

    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls)
        return obj

    # def __call__(self, *args, **kwargs):
    #

obj = Human('张大仙', 73)
# 触发Mytype的__call__方法
#     1、调用Human的__new__方法
#     2、调用Human的__init__方法
#     3、返回初始化好的对象

print(obj.__dict__)


# 运行结果
# {'H_name': '张大仙', 'H_age': 73}

属性查找

# 属性查找
# 对象=》类=》父类=》object
class Mytype(type):
    age = 18
    def __call__(self, *args, **kwargs):
        # print(object.__new__ is self.__new__)
        obj = self.__new__(self)
        self.__init__(obj, *args, **kwargs)
        return obj

class Animal(object):
    # age = 17
    pass

class Human(Animal):
    # age = 16
    pass

class Chinese(Human, metaclass=Mytype):
    # age = 15
    pass

class ScPerson(Chinese):
    # age = 14
    pass

obj = ScPerson()
# print(obj.age)
# print(ScPerson.age)
print(type(Human))



# 运行结果
# <class 'type'>

单例模式

settings.py

class Human:
    def __init__(self, name, age):
        self.name = name
        self.age = age

obj = Human('张大仙', 73)

# 1、模块 (python的模块就是一个天然的单例模式)

from settings import obj
print(obj)
# 2、装饰器

def singleton_mod(cls):
    obj = None
    def wrapper(*args, **kwargs):
        nonlocal obj
        if not obj:
            obj = cls(*args, **kwargs)
        return obj
    return wrapper


@singleton_mod	# Human = singleton_mod(Human)
class Human:    
    def __init__(self, name, age):
        self.name = name
        self.age = age

obj = Human('张大仙', 73)
obj2 = Human('张大仙', 73)
print(obj)
print(obj2)


# 结果
# <__main__.Human object at 0x00000160D8E55E48>
# <__main__.Human object at 0x00000160D8E55E48>
# 3、类绑定方法

class Human:
    obj = None
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_obj(cls, *args, **kwargs):
        if not cls.obj:
            cls.obj = cls(*args, **kwargs)
        return cls.obj



obj = Human.get_obj('张大仙', 73)
obj2 = Human.get_obj('张大仙', 73)
print(obj)
print(obj2)


# 运行结果
# <__main__.Human object at 0x00000202310F5D08>
# <__main__.Human object at 0x00000202310F5D08>
# 4、__new__

class Human:
    obj = None
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __new__(cls, *args, **kwargs):
        if not cls.obj:
            cls.obj = super().__new__(cls)
        return cls.obj



obj = Human('张大仙', 73)
obj2 = Human('张大仙', 73)
print(obj)
print(obj2)


# 运行结果
# <__main__.Human object at 0x00000252C07A5E88>
# <__main__.Human object at 0x00000252C07A5E88>
# 5、元类
​
class Mytype(type):
    obj = None
    def __call__(self, *args, **kwargs):
        if not self.obj:
            # self.obj = super().__call__(*args, **kwargs)
            self.obj = self.__new__(self)
            self.__init__(self.obj, *args, **kwargs)
        return self.obj
​
​
class Human(metaclass=Mytype):
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
​
obj = Human('张大仙', 73)
obj2 = Human('张大仙', 73)
print(obj)
print(obj2)
​
# 运行结果
# <__main__.Human object at 0x0000020B6761FC08>
# <__main__.Human object at 0x0000020B6761FC08>
​
​
# 如果要定义许多类,这些类都要设计成单例模式,那么每个类都要加上metaclass就比较麻烦
# 解决方案:创建一个singleton类,继承元类,然后让所有要设计成单例模式的类,继承自singleton
class Mytype(type):
    obj = None
    def __call__(self, *args, **kwargs):
        if not self.obj:
            # self.obj = super().__call__(*args, **kwargs)
            self.obj = self.__new__(self)
            self.__init__(self.obj, *args, **kwargs)
        return self.obj
​
    
class singleton(metaclass=Mytype):
    pass
​
​
class Human(singleton):
    def __init__(self, name, age):
        self.name = name
        self.age = age
​
​
obj = Human('张大仙', 73)
obj2 = Human('张大仙', 1)
print(obj)
print(obj2)



评论