• 类的实例化


      类的实例是以函数形式调用类对象来创建的。这种方法将创建一个新实例,然后该实例传递给类的__init__()方法。__init__()方法的参数包括新创建的实例self和在调用对象是提供的参数

    class MyClass:
        def __init__(self,name):
            self.name = name
        def say(self):
            print(self.name)
    #类的实例化
    mc = MyClass("aa")

    【1】__init__() "构造器"方法

      当类被调用,实例化的第一步是创建实例对象。一旦对象创建了,Python 检查是否实现了 __init__()方法。默认情况下,如果没有定义(或覆盖)特殊方法__init__(),对实例不会施加任何特别的操作.任何所需的特定操作,都需要程序员实现__init__(),覆盖它的默认行为。如果 __init__()没有实现,则返回它的对象,实例化过程完毕。

      然而,如果__init__()已经被实现,那么它将被调用,实例对象作为第一个参数(self)被传递去,像标准方法调用一样。调用类时,传进的任何参数都交给了__init__()。实际中,你可以想 像成这样:把创建实例的调用当成是对构造器的调用。

    总之

       1、你没有通过调用 new 来创建实例,你也没有定义一个构造器。是 Python 为你创建了对象;      2、__init__(),是在解释器为你创建一个实例后调用的第一个方法,在你开始使用它之前, 这一步可以让你做些准备工作。

      __init__()是很多为类定义的特殊方法之一。其中一些特殊方法是预定义的,缺省情况下,不进行任何操作,比如__init__(),要定制,就必须对它进行重载,还有些方法,可能要按需要去实现。 

    class Student:
        def __init__(self):
            self.name = "学生"
            self.age = 18
        def say(self):
            print(self.name)
    
    s1 = Student()
    print(s1.name)
    print(s1.age)
    
    #当创建Student对象后,在没有调用__init__()方法的前提下,s1就默认拥有了2个属性name和age,原因是__init__()方法是在创建对象后,就立刻被默认调用了
    class Student:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def say(self):
            print(self.name)
    
    s1 = Student("学生",18)
    print(s1.name)
    print(s1.age)
    
    '''
    __init__()方法,在创建一个对象时默认被调用,不需要手动调用
    __init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)
    __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去
    '''

    【2】__new__() "构造器"方法

    class A:
        def __init__(self):
            print("__init__方法")
        def __new__(cls, *args, **kwargs):
            print("__new__方法")
            return object.__new__(cls)
    A()

    总结

      1、__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

      2、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

      3、__init__有一个参数self,就是这个__new__返回的实例,__init____new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

      4、我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

    class A:
        def __init__(self):
            print(self)
            print("__init__方法")
        def __new__(cls, *args, **kwargs):
            print(id(cls))
            print("__new__方法")
            re = object.__new__(cls)
            print(re)
            return re
        
    #print(id(A))
    #4324822888
    a = A()
    #__new__方法
    #<test1.A object at 0x103f1f6d8>
    #<test1.A object at 0x103f1f6d8>
    #__init__方法

    【3】__del__() "解构器"方法

      由于 Python 具有 垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才会执行。 Python 中的解构器是在实例释放前提供特殊处理功能的方法,它们通常没有被实现,因为实例很少被显式释放 

      创建对象后,python解释器默认会调用__init__()方法;当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

    import time
    class Animal(object):
    
        # 初始化方法
        # 创建完对象后会自动被调用
        def __init__(self, name):
            print('__init__方法被调用')
            self.__name = name
    
        # j解构方法
        # 当对象被删除时,会自动被调用
        def __del__(self):
            print("__del__方法被调用")
            print("%s对象马上被干掉了..."%self.__name)
    
    # 创建对象
    dog = Animal("哈皮狗")
    
    # 删除对象
    del dog
    
    cat = Animal("波斯猫")
    cat2 = cat
    cat3 = cat
    print(id(cat),id(cat2),id(cat3))
    print("---马上 删除cat对象")
    del cat
    print("---马上 删除cat2对象")
    del cat2
    print("---马上 删除cat3对象")
    del cat3
    
    print("程序2秒钟后结束")
    time.sleep(2)
    '''
    __init__方法被调用
    __del__方法被调用
    哈皮狗对象马上被干掉了...
    __init__方法被调用
    4369544752 4369544752 4369544752
    ---马上 删除cat对象
    ---马上 删除cat2对象
    ---马上 删除cat3对象
    __del__方法被调用
    波斯猫对象马上被干掉了...
    程序2秒钟后结束
    '''

    注意:

    • 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
    • 当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

    跟踪实例

       Python 没有提供任何内部机制来跟踪一个类有多少个实例被创建了,或者记录这些实例是些什 么东西 。如果需要这些功能,你可以显式加入一些代码到类定义或者__init__()和__del__()中去。最好的方式是使用一个静态成员来记录实例的个数。靠保存它们的引用来跟踪实例对象是很危险的, 因为你必须合理管理这些引用,不然,你的引用可能没办法释放(因为还有其它的引用)! 

    class InstCt:
        count = 0
        def __init__(self):
            InstCt.count += 1
        def __del__(self):
            InstCt.count -= 1
        def howMany(self):
            return InstCt.count
    a = InstCt()
    b = InstCt()
    print(b.howMany())
    # 2
    
    print(a.howMany())
    #2
    
    del b
    print(a.howMany())
    # 1
    
    del a
    print(InstCt.count)
    # 0 
    #此时引用已经为0,如果再使用a.howMany()方法的话,会报错

  • 相关阅读:
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    2013暑假集训B组训练赛第二场
    SPOJ ANARC05H 计数DP
    HDU 2586 LCA-Tarjan
    POJ 1330 LCA最近公共祖先 离线tarjan算法
    Codeforces 176B 经典DP
    UVA 10564 计数DP
    HDU 4901 多校4 经典计数DP
  • 原文地址:https://www.cnblogs.com/Jiangchuanwei/p/8646701.html
Copyright © 2020-2023  润新知