python面向对象

面向对象简介

python完全采用了面向对象的思想,是真正面向对象的变成语言,完全支持面向对象的基本功能,例如:继承、多态、封装等

python中,一切皆为对象。前面学习的数据类型、函数等都是对象

面向过程和面向对象思想

面向过程和面向对象的区别

面向过程和面向对象都是对软件分析、设计和开发的一种思想,它知道着人们以不同的方式去分析、设计和开发软件。C语言是一种典型的面向过程语言,java是一种典型的面向对象语言。

面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。但是,具体到实现部分的围观操作(就是一个个方法),仍然需要面向过程的思路去处理。我们千万不要把面向过程和面向对象队里起来。他们是相辅相成的。面相对象离不开面向过程!

面向对象和面向过程总结

  1. 都是解决问题的思维方式,都是代码组织的方式
  2. 面向过程是一种"执行者思维",解决简单问题可以使用面向过程
  3. 面向对象时一种"设计者思维",解决复杂、需要协作的问题可以使用面向对象

类的定义

类可以看做是一个模版或者图纸,系统根据类的定义来造出对象。

类:我们叫做class。对象:我们叫做object,instance(实例)

python中,"一切皆为对象"。类也称为"类对象",类的实例也称为"实例对象"。

定义类的语法格式如下:

class Student(object):
    def __init__(self, name, score, *jineng):
        self.name = name
        self.score = score
        self.skill = jineng

    def say_score(self):
        print("{}的分数为{}".format(self.name, self.score))

    def attack(self, skill):
        print("{}使用了{}技能".format(self.name, skill))

    def main(self):
        """
        整个对象的主函数
        :return:
        """
        oder = input("请输入你要使用的技能1.九阴白骨爪,2.六脉神剑")
        if oder == 1:
            self.attack(self.skill[0])
        else:
            self.attack(self.skill[1])


if __name__ == '__main__':
    student1 = Student("张三", 19, '九阴白骨爪', '六脉神剑')
    # print(student1.skill[0])
    student1.main()

python对象完整内存结构

类是抽象的,也称为"对象的模版"。

__init__构造方法和__new__方法

初始化对象,我们需要定义构造函数__init__()方法。构造方法用于执行"实例对象的初始化工作",即对象创建后,初始化当前对象的相关属性,无返回值。

class CarFactory(object):
    __obj = None
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)

        return cls.__obj

    def __init__(self):
        if CarFactory.__init_flag:
            print("init.....")
            CarFactory.__init_flag = False

    def createCar(self, brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "位置品牌,无法创建"

在 Python 中,clsself 的作用是不同的。

  • self: 代表当前对象的实例。通常在实例方法中使用,以访问实例的属性和方法。

  • cls : 代表当前类,通常在类方法或特殊方法(如 __new__)中使用,以访问类的属性和方法。

在你提供的代码中,cls 用于 __new__ 方法,表示当前类 MySingleton,而不是类的实例。这是用来创建类的实例而不是访问特定实例的属性。

所以,虽然两者的角色有相似之处(都是引用),但 clsself 是在不同的上下文中使用的。

从GPT-4o获取更智能的答案

实例属性

实例属性是从属于实例对象的属性,也称为"实例变量"。他的使用有如下几个要点:

  1. 实例属性一般在__init__()方法中通过如下代码定义:
    self.实例属性名=初始值
  2. 在本类的其他实例方法中,也是通过self进行访问
    self.实例属性名
  3. 创建实例对象后,通过实例对象访问:
    obj01=类名()
    obj01.实例属性名=值

实例方法

函数和方法的区别

  1. 都是用来完成一个功能的语句块,本质一样。
  2. 方法调用时,通过对象来调用。方法从属于特定实例对象,普通函数没有这个特点
  3. 直观上看,方法定义时需要传递self,函数不需要

实例对象的方法调用本质

class Student(object):
    def __init__(self, name, score, *jineng):
        self.name = name
        self.score = score
        self.skill = jineng

    def say_score(self):
        print("{}的分数为{}".format(self.name, self.score))

    def attack(self, skill):
        print("{}使用了{}技能".format(self.name, skill))

    def main(self):
        """
        整个对象的主函数
        :return:
        """
        oder = input("请输入你要使用的技能1.九阴白骨爪,2.六脉神剑")
        if oder == 1:
            self.attack(self.skill[0])
        else:
            self.attack(self.skill[1])


if __name__ == '__main__':
    student1 = Student("张三", 19, '九阴白骨爪', '六脉神剑')
    # print(student1.skill[0])
    Student.attack(student1, '九阴白骨爪')
    student1.main()

其他操作

  1. dir(obj)可以获得对象的所有属性、方法
  2. obj.__dict__对象的属性字典
  3. pass空语句
  4. isintance(对象,类型)判断对象是不是指定类型

类属性

类属性是从属于"类对象"的属性,也称为"类对象"。由于,类属性从属于类对象,可以被所有实例对象共享

类属性的定义方式:

class 类名:
    类变量名=初始值

在类中或者类的外面,我们可以通过:类名.类变量名来读写

内存分析实例对象和类对象创建过程

class Student(object):
    company = "重庆交通大学"  # 类属性
    count = 0  # 类属性

    def __init__(self, name, score):
        self.name = name  # 实例属性
        self.score = score
        Student.count = Student.count + 1

    def say_score(self):  # 实例方法
        print("我的公司是:", Student.company)
        print(self.name, '的分数为:', self.score)


if __name__ == '__main__':
    s1 = Student('王总', 80)  # s1是实例对象,自动调用__init__()方法
    s2 = Student('张三', 70)
    s1.say_score()
    print('一共创建了{}个Student对象'.format(Student.count))

类方法

类方法是从属于"类对象"的方法。类方法通过装饰器@classmethod来定义,格式如下:

@classmethod
def 类方法(cls [,形参列表]):
    方法体

注意事项

  1. @classmethod必须位于方法上面一行
  2. 第一个cls必须有;cls指的就是"类对象"本身
  3. 调用类方法格式:类名.类方法名(参数列表)。参数列表中,不需要也不能给cls传值
  4. 类方法中访问实例属性和实例方法会导致错误
  5. 子类继承父类方法时,传入clsshi子类对象,而非父类对象

对于类方法不可用实例对象中的数据。!!!

静态方法

python中允许定义与"类对象"无关的方法,称为"静态方法"

"静态方法"和在模块中定义的普通函数没有区别,只不过"静态方法"放到了"类的名字空间里面",需要通过"类调用"。

在 Python 中,staticmethod 函数是一种装饰器,用于将函数转换为静态方法。静态方法与实例方法和类方法不同,它们不需要类实例作为第一个参数,也不需要类作为第一个参数,因此可以在不需要访问类或实例属性的情况下调用。

静态方法通过装饰器@staticmethod来定义,格式如下:

@staticmethod
def 静态方法名([形参列表]):
    方法体

注意事项:

  1. @staticmethod必须位于方法上面一行
  2. 调用静态方法格式:类名.静态方法名(参数列表)
  3. 静态方法中访问实例属性和实例方法会导致错误

静态对象也不能使用实例对象的数据!!!

class Student(object):
    company = "SXT"  # 类属性

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

    @classmethod
    def printCompany(cls):
        print("这个学生的company属性为:", cls.company)

    @staticmethod
    def add(a, b):
        print("{}+{}={}".format(a, b, a + b))
        return a + b


if __name__ == '__main__':
    sum = Student.add(10, 20)
    print(sum)
    student = Student('李阳')
    student.add(10, 20)

del()

del()称为"析构方法",用于实现对象被销毁时所需的操作。比如:释放对象占用的资源,例如:打开的文件资源,网络连接等。

python实现自动的垃圾回收,当对象没有被引用时(引用计数为0),有垃圾回收器调用__del__()

我们也可以通过del语句删除对象,从而保证调用__del__()。

系统会自动提供__del__方法,一般不需要自定义析构方法。

call方法和可调用对象

  1. python中,凡是可以将()直接应用到自身并执行,都称为可调用对象。

  2. 可调用对象包括自定义的函数、Python内置函数。

  3. 定义了__call__()的对象,称为"可调用对象",即该对象可以像函数一样被调用

  4. 该方法使得实例对象可以调用普通函数那样,以"对象名()的形式使用"

    class Car(object):
    def init(self, age, money):
    self.money = money
    self.age = age

     def __call__(self, age, money):
         print("call方法")
         print("车龄{0}\n金额{1}".format(age, money))
    
     def say_money(self):
         print("常规方法")
         print("车龄{0}\n金额{1}".format(self.age, self.money))
    

    if name == 'main':
    car = Car(3, 200000)
    car.say_money()
    print()
    car(3, 20000)#使用了call函数,可以使实例对象能够像函数名一样调用

方法没有重载

如果我们在类体中定义了多个重名的方法,只有最后一个方法有效

建议:不要使用重名的方法!python中方法没有重载

  • 在其他一些语言(比如:java)中,可以定义多个重名的方法,只要保证方法签名唯一即可。方法签名包含3个部分:方法名、参数数量、参数类型。

  • python中,方法的参数没有声明类型(调用时确定参数的类型),参数的数量也可以由可变参数控制。因此,python中没有方法的重载

    python中没有方法的重载。定义多个同名的方法,只有最后一个有效

    class Person(object):
    name = '李阳'

      def say_hi(self):
          print("hello")
    
      def say_hi(self):
          print("{},hello".format(self.name))
    

    if name == 'main':
    person = Person()
    person.say_hi()

方法的动态性

python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有方法

# python中没有方法的重载。定义多个同名的方法,只有最后一个有效
class Person(object):
    name = '李阳'

def say_hi(self):
    print("hello")

def say_hi(self):
    print("{},hello".format(self.name))


if __name__ == '__main__':
    person = Person()
    person.say_hi()

为什么这里的对象外部函数,需要传入参数self,但是在对象调用函数的时候为什么不需要传入参数。因为这里person.say_h1()实际上是默认传入了person一个实例对象。

私有属性和私有方法(实现封装)

python对于类的成员没有严格的访问控制限制,这于其他面向对象语言有区别。关于私有属性和私有方法,有如下要点:

  1. 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。

  2. 类内部可以访问私有属性(方法)

  3. 类外部不能直接访问私有属性(方法)

  4. 类外部可以通过_类名_私有属性(方法)名访问私有属性(方法)

    class Employee(object):
    __company = "重庆" # 解释器运行时,把__company转成了_Employee__company

     def __init__(self, name, age):
         self.name = name
         self.__age = age
         self.age = age
    
     def say_company(self):
         print("我的公司是:", Employee.__company)
         print("我的年龄是:", self.__age)
    

    print(dir(Employee))

    print(Employee._Employee__company)
    a = Employee("王总", 18)
    a.say_company()
    print("这是一个公共属性", a.age)
    print("这是一个私有属性", a._Employee__age)

私有方法

class Employee(object):
    __company = "重庆"  # 解释器运行时,把__company转成了_Employee__company

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

    def say_company(self):
        print("我的公司是:", Employee.__company)
        print("我的年龄是:", self.__age)


    def __work(self):
        print("我的工作就是玩!")


# print(dir(Employee))
print(Employee._Employee__company)
a = Employee("王总", 18)
a.say_company()
a._Employee__work()
print("这是一个公共属性", a.age)
print("这是一个私有属性", a._Employee__age)

@property装饰器

@property是一个内置的装饰器,允许你通过方法来定义一个属性,使得你能够以访问属性的方式来调用方法。它通常用于控制属性的访问、修改和删除操作,同时隐藏一些复杂的实现细节。

@property主要用于帮助我们处理属性的读操作、写操作。对于某一个属性,我们可以直接通过:

emp1.salary=3000

如上的操作读操作、写操作。但是,这种做法不安全。比如,我需要限制薪水必须为1-10000的数字。这时候,我们就需要通过使用装饰器@property来处理

主要作用

  1. 简化属性访问:通过 @property 装饰器可以将方法转化为属性,使得用户在访问时无需直接调用方法,而是像访问普通属性一样使用。

  2. 封装逻辑:可以在属性的访问和修改过程中加入额外的逻辑,比如验证数据的有效性或进行其他计算。

  3. 提供只读属性:通过 @property 可以定义只读属性,避免直接修改某些敏感属性。

  4. 控制属性的读取、修改和删除:可以使用 @property 配合 @<property_name>.setter@<property_name>.deleter 来定义属性的设置器和删除器,控制属性的赋值和删除操作。

    class Employee(object):
    def init(self, name, salary):
    self.name = name
    self.__salary = salary

     @property
     def salary(self):
         print("薪资是:", self.__salary)
         return self.__salary
    
     @salary.setter
     def salary(self, salary):
         if 0 < salary < 1000000:
             self.__salary = salary
         else:
             print("薪资录入错误!只能在0-100000之间!")
    
     @salary.deleter
     def salary(self):
         print("Deleting salary...")
         del self.__salary
    

    if name == 'main':
    emp1 = Employee('老高', 30000)
    print(emp1.salary)
    emp1.salary = 50000
    print(emp1.salary)
    del emp1.salary
    print(emp1.salary)

属性和方法命名总结

  1. _xxx:保护成员,不能用from module import *导入,只有类对象和子对象能访问这些成员。
  2. xxx:系统定义的特殊成员
  3. __xxx:类中的私有成员,只有类对象自己能访问,子类对象也不能访问。(但,在类外部可以通过对象名._类名__xxx这种特殊方法访问。python不存在严格意义的私有成员)

None对象的特殊性

None不是False,None不是0,None不是字符串。None和任何其他的数据类型比较永远返回False

a = None
if a is None and a == None:
    print("a是None")  # 会执行
if a==False or a==0:
    print("None不等于False")

if语句判断时,空列表、空字典、空元组、0等一系列表空和无的对象会被转换为Fasle

面向对象三大特征介绍

python是面向对象的语言,支持面向对象编程的三大特性:继承、封装(隐藏)、多态

封装(隐藏)

隐藏对象的属性和实现细节,只对外提供必要的方法。相当于将"细节封装起来",只对外暴露"相关调用方法"。

通过前面学习的"私有属性、私有方法"的方式、实现"封装"。python追求简洁语法,没有严格的语法级别的"访问控制符",更多的是依靠程序员自觉实现

继承

继承可以让子类具有父类的特性,提高了代码的重用性

从设计上是一种增量进化,原有父类设计不变的情况下,可以增加新的功能,或者改进已有的算法。

多态

多态指同一个方法调用由于对象不同会产生不同的行为。生活中这样的例子比比皆是;同样是休息方法,人不同休息方法不同。张三休息是睡觉,李四休息是玩游戏,程序员休息是"敲几行代码"。

继承

继承是面向对象编程的三大特征之一。继承让我们更加容易实现类的扩展,实现代码的重用,不用在重新发明轮子

如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,就大大降低了工作难度。已有的类,我们陈伟"父类或者基类",新的类,我们称为"子类或者派生类"

语法格式

Python支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:

class 子类类名(父类1[,父类2,...])
    类体

如果在类定义中没有指定父类,则默认父类是object类。也就是说,object是所有类的父类,里面定义了一些所有类共有的默认实现,比如:new()

关于构造函数:

  1. 子类不重写__init__,实例化子类时,会自动调用父类定义的__init__。

  2. 子类重写了__init__时,实例化子类,就不会调用父类已经定义的__init__。

  3. 如果重写了__init__时,要继承父类的构造方法,可以使用super关键字,也可以使用如下格式调用:

    class Student:
    pass

    class Car:#父类是object
    pass

    class Benz(Car):
    pass

    class Person(object):
    def init(self, name, age):
    print("创建Person")
    self.name = name
    self.age = age

     def say_age(self):
         print("{0}的年龄为{1}岁".format(self.name, self.age))
    

    class Student(Person):
    def init(self, name, age, score):
    self.name = name
    self.age = age
    self.score = score

    s1 = Student("老王", 18, 90)
    s1.say_age()

    class Person(object):
    def init(self, name, age):
    print("创建Person")
    self.name = name
    self.age = age

     def say_age(self):
         print("{0}的年龄为{1}岁".format(self.name, self.age))
    

    class Student(Person):
    def init(self, name, age, score):
    #调用父类构造方法,可以使用如下两种方式:
    Person.init(self, name, age)
    #super(Student, self).init(name, age)
    print("创建Student类")
    self.score = score

    s1 = Student("老王", 18, 90)
    s1.say_age()

类成员的继承和重写

  1. 成员继承:子类继承了父类除构造方法之外的所有成员,私有属性和私有方法也可以被继承

  2. 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为"重写"

    class Person(object):
    def init(self, name, age):
    print("创建Person")
    self.name = name
    self.__age = age

     def say_age(self):
         print("{0}的年龄为{1}岁".format(self.name, self.__age))
    

    class Student(Person):
    def init(self, name, age, score):
    # Person.init(self, name, age)
    super(Student, self).init(name, age)
    print("创建Student类")
    self.score = score

    s1 = Student("老王", 18, 90)
    s1.say_age()

    class Person(object):
    def init(self, name, age):
    self.name = name
    self.age = age

     def say_age(self):
         print(self.name, "的年龄是:", self.age)
    
     def say_name(self):
         print("我是", self.name)
    

    class Student(Person):
    def init(self, name, age, score):
    Person.init(self, name, age)
    self.score = score

     def say_score(self):
         print(self.name, "的分数是:", self.score)
    
     def say_name(self):
         print("报告老师,我是", self.name)#父类方法的重写
    

    s1 = Student("老高", 15, 85)
    s1.say_score()
    s1.say_name()
    s1.say_age()

查看类的继承层次结构

通过类的方法mro()或者类的属性__mro__可以输出这个类的继承层次结构

class A: pass
class B(A): pass
class C(B): pass
print(C.mro())

object根类

object类是所有类的父类,因此所有的类都有object类的属性和方法。我们显然有必要深入研究一下object类的结构。对于我们继续深入学习python很有好处

dir()查看对象属性

为了深入学习对象,先学习内置函数dir(),他可以让我们方便的看到指定对象所有的属性

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

    def say_age(self):
        print(self.name, "的年龄是:", self.age)


obj = object()
print(dir(obj))

s2 = Person("老高", 18)
print(dir(s2))
print(s2.say_age)
print(type(s2.say_age))

重写__str__()方法

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age

    def __str__(self):
        """
        将对象转化成一个字符串描述,一般用于print方法
        :return:
        """
        print("重写__str__方法")
        return "名字是:{0},年龄是{1}".format(self.name, self.__age)


p = Person("老高", 18)
print(p)
s = str(p)

多重继承

python支持多重继承,一个子类可以有多个"直接父类"。这样,就具备了"多个父类"的特点。但是由于这样会被"类的整体层次"搞的异常复杂,尽量避免使用

class A(object):
    def aa(self):
        print("这是A的方法")


class B(object):
    def bb(self):
        print("这是B的方法")


class C(B, A):
    def cc(self):
        print("这是C的方法")

if __name__ == '__main__':
    c = C()
    c.cc()
    c.bb()
    c.aa()

MRO方法解析顺序

Python支持多继承、如果父类中有相同名字的方法,在子类中没有指定父类名时,解释器将"从左向右"按顺序搜索。

MRO(Method Resolution Order):方法解析顺序。我们可以通过mro()方法获得"类的层次结构",方法解析顺序也是按照这个"类的层次结构"寻找的。

class A(object):
    def aa(self):
        print("aa")

    def say(self):
        print("say AAA!")


class B(object):
    def bb(self):
        print("bb")

    def say(self):
        print("say BBB!")


class C(B, A):
    def cc(self):
        print("cc")


c = C()
print(C.mro())  # 打印类的层次结构
c.say()  # 解释器寻找方法是"从左到右"的方式寻找,此时会执行B类中的say()

super()获得父类的定义

class A(object):
    def __init__(self):
        print("A的构造方法")

    def say(self):
        print("A:", self)
        print("say AAA")


class B(A):
    def __init__(self):
        super(B, self).__init__()#调用父类的构造方法
        print("B的构造方法")

    def say(self):
        #A.say(self) 调用父类的say方法
        super(B, self).say()#通过super()调用父类的方法
        print("say BBB")

b=B()
b.say()

多态

多态是指同一个方法调用由于对象不同可能会产生不同的行为

比如:现实生活中,同一个方法,具体实现会完全不同。比如:同样是调用人"吃饭"的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭

关于多态要注意一下2点:

  1. 多态是方法的多态,属性没有多态。

  2. 多态的存在有2个必要条件:继承、方法重写

    class Animal(object):
    def shout(self):
    print("动物叫了一声")

    class Dog(Animal):
    def shout(self):
    print("小狗,汪汪")

    class Cat(Animal):
    def shout(self):
    print("小猫,喵喵喵")

    def animalShout(animal):
    animal.shout() # 会产生多态,传入的对象不同,则调用的方法也不一样

    animalShout(Dog())
    animalShout(Cat())

对象的浅拷贝和深拷贝

浅拷贝

python拷贝一般都是浅拷贝。拷贝时,对象包含的子对象内容不拷贝。因此,源对象和拷贝对象会引用同一个子对象

import copy


class MobilePhone(object):
    def __init__(self, cpu):
        self.cpu = cpu


class CPU(object):
    pass


c = CPU()
m = MobilePhone(c)

print("浅拷贝")
m2 = copy.copy(m)  # 浅拷贝,m2是m对象的一个浅拷贝对象
print("m:", id(m))
print("m2:", id(m2))
print("m中的cpu:", id(m.cpu))
print("m2中的cpu:", id(m2.cpu))

深拷贝

使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象。源对象金额拷贝对象所有的子对象也不同。

import copy


class MobilePhone(object):
    def __init__(self, cpu):
        self.cpu = cpu


class CPU(object):
    pass


c = CPU()
m = MobilePhone(c)

print("深拷贝...")
m3 = copy.deepcopy(m)  # 深拷贝
print("m", id(m))
print("m3", id(m3))
print("m中的cpu", id(m.cpu))
print("m3中的cpu", id(m3.cpu))

组合

除了继承,"组合"也能实现代码的复用!"组合"核心是"将父类对象作为子类的属性"。

class CPU(object):
    def calculate(self):
        print("正在计算,算个12345!")


class Screen(object):
    def show(self):
        print("显示一个好看的画面,亮瞎你的钛合金眼")


class MobilePhone(object):
    def __init__(self, cpu, screen):
        self.cpu = cpu
        self.screen = screen


c = CPU()
s = Screen()
m = MobilePhone(c, s)
m.cpu.calculate()
m.screen.show()

设计模型

工厂模式实现

class Benz(object):
    pass

class BMW(object):
    pass

class BYD(object):
    pass

class CarFactory(object):
    def createCar(self, brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "位置品牌,无法创建"


factory = CarFactory()
c1 = factory.createCar("奔驰")
c2 = factory.createCar("宝马")
print(c1)
print(c2)

单例模式实现

单例模式的核心作用就是确保一个雷只有一个实例,并且提供一个访问该实例的全局访问点。

单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个"单例对象",然后永久主流内存中,从而极大地降低开销

!!!单例模式有多重实现的方式,我们这里推荐重写__new__()的方法。

class MySingleton(object):
    __obj = None
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

    def __init__(self, name):
        if MySingleton.__init_flag:
            print("初始化第一个对象...")
            self.name = name
            MySingleton.__init_flag = False


a = MySingleton("aa")
print(a.name)
b = MySingleton("bb")
print(b.name)

工厂和单例模式结合

class CarFactory(object):
    __obj = None
    __init_flag = True

    def __new__(cls, *args, **kwargs):
        if cls.__obj == None:
            cls.__obj = object.__new__(cls)

        return cls.__obj

    def __init__(self):
        if CarFactory.__init_flag:
            print("init.....")
            CarFactory.__init_flag = False

    def createCar(self, brand):
        if brand == "奔驰":
            return Benz()
        elif brand == "宝马":
            return BMW()
        elif brand == "比亚迪":
            return BYD()
        else:
            return "位置品牌,无法创建"


factory = CarFactory()
c1 = factory.createCar("奔驰")
c2 = factory.createCar("宝马")
print(c1)
print(c2)
factory2 = CarFactory()
print(factory)
print(factory2)

单例模式和工厂的结合,factory工厂只能创建一个实例对象,不能多创建,但是生产车的实力对象,可以多生产。

相关推荐
zhangfeng11334 分钟前
selenium已经登陆了 我怎么查看 网页 在fRequest xhr 的数据呢
开发语言·python
music&movie3 小时前
代码填空任务---自编码器模型
python·深度学习·机器学习
风一样的树懒4 小时前
Python使用pip安装Caused by SSLError:certificate verify failed
人工智能·python
测试最靓仔4 小时前
allure报告修改默认语言为中文
python·自动化
AI视觉网奇5 小时前
imageio 图片转mp4 保存mp4
python
凡人的AI工具箱5 小时前
每天40分玩转Django:Django DevOps实践指南
运维·后端·python·django·devops
shaxin观yin5 小时前
python反序列化+沙箱逃逸++js+redis
python·学习·https
专注于开发微信小程序打工人6 小时前
庐山派k230使用串口通信发送数据驱动四个轮子并且实现摄像头画面识别目标检测功能
开发语言·python
白雪公主的后妈6 小时前
Python爬虫基础——XPath表达式
爬虫·python·lxml·etree