新式类和经典类的区别&类的特殊方法&单例模式

目录:

新式类和经典类的区别:

1)首先,写法不一样:

 class A:      #经典类写法

 pass

class B(object):  #新式类写法

 pass

2)多继承中,新式类采用广度优先搜索,而旧式类是采用深度优先搜索,python3中全是广度优先

3)在继承中新式类和经典类写法区别

SchoolMember.__init__(self,name,age,sex)  #经典类写法
                    
super(Teacher,self).__init__(name,age,sex)  #新式类写法                   

在这里插入图片描述
代码展示

class D:
    def talk(self):
        print('D')

class B(D):
    pass
    # def talk(self):
    #     print('B')

class C(D):
    pass
    def talk(self):
        print('C')

class A(B,C):
    pass
    # def talk(self):
    #     print('A')

a = A()
a.talk()

重写特殊的构造方法

  1. 注:如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不能给被正确的初始化
  2. 其实调用超类构造方法很容易,SongBird类中只添加一行代码
python 经典类写法:    Bird.__init__(self)

新式类写法:    super(SongBird,self).__init__()
  1. 如果将下面代码没有2中的那句调用父类Bird中的self.hungry方法会报错
if self.hungry == True:
AttributeError: SongBird instance has no attribute 'hungry'                           

新式类,经典类,无超类构造方法报错

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry == True:
            print("Aaaah...")
            self.hungry = False
        else:
            print("no, thanks")
a = Bird()
a.eat()
a.eat()

class SongBird(Bird):
    def __init__(self):
        # Bird.__init__(self)     # 经典类写法
        # super(SongBird,self).__init__()   # 新式类写法
        self.sound = 'Squawk'
    def sing(self):
        print(self.sound)
b = SongBird()
b.sing()
b.eat()

类的特殊方法

__doc__  表示类的描述信息
class Foo:
    """ 输出类的描述类信息 """
    def func(self):
        pass
print(Foo.__doc__) #运行结果:描输出类的描述类信息
__call__ 对象后面加括号,触发执行
  • 作用:构造方法__init__的执行是由创建对象触发的,即:对象 = 类名()
  • 对于 call 方法的执行是由对象后,括号触发的,即:对象() 或者 类()()

执行__call__方法

class Dog(object):
    def __init__(self,name):
        self.name = '实例变量'
        self.name = name
    def __call__(self, *args, **kwargs):
        print("running call")
        print(args,kwargs)
d = Dog("ChenRonghua")
d(name='tom')               # 如果只实例化,而不d()调用,__call__函数不会执行

# 运行结果:
# running call
# () {'name': 'tom'}
 __str__ 如果一个类中定义了__str__方法,在打印对象时,默认输出该方法的返回值**
class Foo:
    def __str__(self):
        return 'alex li'
obj = Foo()
print(obj)     # 输出:alex li
 __dict__ 查看类或对象中的所有成员
class Province:
    country = 'China'
    def __init__(self, name, count):
        self.name = name
        self.count = count
    def func(self, *args, **kwargs):
        print('func')
# 获取类的成员,即:静态字段、方法、
print(Province.__dict__)
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}

obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'}

obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}
 _getitem__、__setitem__、__delitem__ 作用:用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo(object):
    def __getitem__(self, key):
        print('__getitem__', key)

    def __setitem__(self, key, value):
        print('__setitem__', key, value)

    def __delitem__(self, key):
        print('__delitem__', key)

obj = Foo()
result = obj['k1']           # __getitem__ k1
obj['k2'] = 'wupeiqi'        # __setitem__ k2 wupeiqi
del obj['k1']                # __delitem__ k1
__new__ \ __metaclass__   作用: __metaclass__定义这个类以怎样的形式被创建
class User(object):
    def __init__(self,name,age):
        print('__init__')

    def __new__(cls, *args, **kwargs):
        print("__new__",args,kwargs)
        return object.__new__(cls)         # 调用一下object的__new__方法否则不往下走
d = User('tom',100)

# 运行结果:
# __new__ ('tom', 100) {}
# __init__

__new__和__init__的区别

  • __new__是一个静态方法,而__init__是一个实例方法.
  • __new__方法会返回一个创建的实例,而__init__什么都不返回.
  • 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  • 当创建一个新实例时调用__new__,初始化一个实例时用__init__.

type生成类调用顺序

  • new : 先于__init__方法,每生成一个实例执行一次
  • init : __init__方法每生成一个实例对象就会执行一次
  • call : 后与__init__方法,C()() 使用类再加一个括号调用, C为类名称
  • del : 析构方法,删除无用的内存对象(当程序结束会自动自行析构方法)
class Student(object):
    def __new__(cls, *args, **kwargs):
        print('__new__')
        return object.__new__(cls)    # 必须返回父类的__new__方法,否则不不执行__init__方法,无法创建实例

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

    def __str__(self):                # 作用:打印实例时显示指定字符串,而不是内存地址
        print('__str__')
        return self.name

    def __call__(self, *args, **kwargs):        # 当执行C()(*args) 或者 s1(*args) 就会执行__call__
        print('__call__',*args)

    def __del__(self):                # 作用:清除无用的实例对内存的暂用
        print('__del__')

#1、实例化时机会执行__new__、__init__
s1 = Student('tom')

#2、执行 实例()  就会执行__call__ 方法,并将参数传递给__call__函数
s1('call01')

#3、当打印实例时就会执行 __str__ 方法下返回的字符串(默认返回的实例地址)
print(s1)

#4、析构方法:当删除实例时就会调用 __del__ 方法
del s1
# 析构方法作用:在程序结束后会自动执行析构方法删除所有实例
# 但是在程序运行时有很多实例是无用的,但是python内存回收机制却不会自动删除他们,这样就浪费内存
# 我们可以执行 del s1 ,那么在程序运行时,python内存回收机制会检测到这些实例时无用的,才会删除
# 其实我们执行del s1,并没有回收内存,只不过是摘除门牌号,python内存回收机制发现没有门牌号后会自动回收内存

单例模式原理及作用

  1. 单例模式:永远用一个对象得实例,避免新建太多实例浪费资源
  2. 实质:使用__new__方法新建类对象时先判断是否已经建立过,如果建过就使用已有的对象
  3. 使用场景:如果每个对象内部封装的值都相同就可以用单例模式

创建单例模式举例

class Foo(object):
   instance = None
   def __init__(self):
      self.name = 'alex'

   def __new__(cls, *args, **kwargs):
      if Foo.instance:
         return Foo.instance
      else:
         Foo.instance = object.__new__(cls,*args,**kwargs)
         return Foo.instance

obj1 = Foo()       # obj1和obj2获取的就是__new__方法返回的内容
obj2 = Foo()
print(obj1,obj2)   # 运行结果: <__main__.Foo object at 0x00D3B450>    <__main__.Foo object at 0x00D3B450>

# 运行结果说明:
# 这可以看到我们新建的两个Foo()对象内存地址相同,说明使用的•同一个类,没有重复建立类

参考来自于此

发布了75 篇原创文章 · 获赞 62 · 访问量 4664

猜你喜欢

转载自blog.csdn.net/weixin_45139342/article/details/104755271