魔方方法篇第一章--------构造与析构

我们最为熟知的基本的魔法方法就是 __init__ ,我们可以用它来指明一个对象初始化的行为。然而,当我们调用 x = SomeClass() 的时候, __init__ 并不是第一个被调用的方法。事实上,第一个被调用的是 __new__ ,这个 方法才真正地创建了实例。当这个对象的生命周期结束的时候(指类被删除之后), __del__ 会被调用。让我们近一步理解这三个方法:

__new__(cls,[...)
__new__ 是对象实例化时第一个调用的方法,它只取下 cls 参数,并把其他参数传给 __init__ 。 __new__ 很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。我不打算深入讨论 __new__ ,因为它并不是很有用, Python文档 中 有详细的说明。

__init__(self,[...])
类的初始化方法。它获取任何传给构造器的参数(比如我们调用 x = SomeClass(10, ‘foo’) , __init__ 就会接到参数 10 和 ‘foo’ 。 __init__ 在Python的类定义中用的最多。

__del__(self)
__new__ 和 __init__ 是对象的构造器, __del__ 是对象的销毁器。它并非实现了语句 del x (因此该语句不等同于 x.__del__())。而是定义了当对象被垃圾回收时的行为。 当对象需要在销毁时做一些处理的时候这个方法很有用,比如 socket 对象、文件对象。但是需要注意的是,当Python解释器退出但对象仍然存活的时候, __del__ 并不会 执行。 所以养成一个手工清理的好习惯是很重要的,比如及时关闭连接。

看下面例子,关于__new__ 和 __init__ 的调用会有一些理解:

class Ceshi1:
    def __new__(cls, *args, **kwargs):
        print("__new__正在调用")
        return object.__new__(cls, *args, **kwargs)
    def __init__(self):
        print("__init__正在调用")
    def __del__(self):
        print("__del__正在调用")

以下是运行过程

>>> c = Ceshi1()
__new__正在调用
__init__正在调用
>>> del c
__del__正在调用
class Person(object):
    def __new__(cls, name, age):
        print('__new__在实例化之前被调用。')
        return object.__new__(cls)

    def __init__(self, name, age):
        print("__init__在实例化后被调用。")
        self.name = name
        self.age = age

    def __str__(self):
        return f'<人物是{self.name},年龄为{self.age}>'

    def __del__(self):
        print("调用__del__魔法")

以下是运行过程:

# >>> c = Person("Tony",24)
# __new__在实例化之前被调用。
# __init__在实例化后被调用。
# >>> print(c)
# <人物是Tony,年龄为24>
# >>> del c
# 调用__del__魔法
class Foo:
    def __new__(cls, *args, **kwargs):
        print("__new__正在调用")
        print(cls)
        print(object.__new__(cls, *args, **kwargs))
        return object.__new__(cls, *args, **kwargs)
    def __init__(self):
        print("__init__正在调用")
        print(self)
foo = Foo()
#================运行如下=============
# __new__正在调用
# <class '__main__.Foo'>
# <__main__.Foo object at 0x0000000003070F28>
# __init__正在调用
# <__main__.Foo object at 0x0000000003070F28>
# 总结先执行__new__方法,再执行__init__方法。实例化是在__new__中完成的,进入__init__时,self已经实例化了。
=================================分割线===================================================
__new__(cls,[...)
__new__ 是对象实例化时第一个调用的方法,它只取下 cls 参数,并把其他参数传给 __init__
第一个参数cls是当前正在实例化的类。
如果要得到当前类的实例,应当在当前类中的 __new__() 方法语句中调用当前类的父类的 __new__() 方法
例如,如果当前类是直接继承自 object,那当前类的 __new__() 方法返回的对象应该为:
def __new__(cls, *args, **kwargs):
...
return object.__new__(cls)
如下面的例子:
看完下面几个例子尝试自己动手写几个关于new魔法的使用方法
class CapStr(str):
    "小写转换大写"
    def __new__(cls,string):
        string = string.upper()
        return str.__new__(cls,string)

class C2F(float):
    "摄氏度转换为华氏度"
    def __new__(cls, arg=0.0):
        return float.__new__(cls, arg * 1.8 + 32)

class Nint(int):
    "传入的参数是字符串的时候,返回该字符串中所有字符的 ASCII 码的和(使用 ord() 获得一个字符的 ASCII 码值)"
    def __new__(cls, arg=0):
        if isinstance(arg, str):
            total = 0
            for each in arg:
                total += ord(each)
            arg = total
        return int.__new__(cls, arg)

class PositiveInteger(int):
    "永远都是正数的整数类型"
    def __new__(cls, value):
        return int.__new__(cls, abs(value))
__init__(self,[...])
类的初始化方法。它获取任何传给构造器的参数(比如我们调用 tt = Test(100,200) ,
__init__ 就会接到参数 100 和 200 。 __init__ 在Python的类定义中用的最多。
举例:看完自己尝试些几个关于init魔法方法的使用
class Test():
    """
    用于初始化类
    """
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def res(self):
        return (self.a, self.b)

class Rect:
    "矩形类,长宽,求面积与周长"
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def getPeri(self):
        return (self.x + self.y) * 2

    def getArea(self):
        return self.x * self.y
#你可能在想什么会需要用到这个__init呢?
#比如上面这个矩形类,因为你需要知道它的长和宽,才能求周长与面积
#打个比方,假如你要构造一个圆类,椭圆类呢?是不是需要定义一些必要参数,才能求出他的面积或者周长。

猜你喜欢

转载自www.cnblogs.com/Stubbon/p/10225927.html
今日推荐