类的实例化

  类的实例是以函数形式调用类对象来创建的。这种方法将创建一个新实例,然后该实例传递给类的__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()方法的话,会报错

 

 

posted @ 2018-03-25 20:45  今晚打老虎i2016  阅读(545)  评论(0编辑  收藏  举报