1. 程式人生 > 其它 >python中__new__方法詳解及使用

python中__new__方法詳解及使用

__new__的作用

在Python中new方法與init方法類似,但是如果兩個都存在那麼new先執行,先呼叫了__new__()方法,在呼叫__init__()初始化

object將__new__()方法定義為靜態方法,並且至少需要傳遞一個引數cls,cls表示需要例項化的類,此引數在例項化時由Python直譯器自動提供。

__new__()必須要有返回值,返回例項化出來的例項,需要注意的是,可以return父類__new__()出來的例項,也可以直接將object的__new__()出來的例項返回。

__init__()有一個引數self,該self引數就是__new__()返回的例項,__init__()在__new__()的基礎上可以完成一些其它初始化的動作,__init__()不需要返回值。

若__new__()沒有正確返回當前類cls的例項,那__init__()將不會被呼叫,即使是父類的例項也不行。

我們可以將類比作製造商,__new__()方法就是前期的原材料購買環節,__init__()方法就是在有原材料的基礎上,加工,初始化商品環節。

實際應用過程中,我們可以這麼使用:

該類中的__new__()方法的使用,就是再進行初始化之前,檢查快取中是否存在該物件,如果存在則將快取存放物件直接返回,如果不存在,則將物件放至快取中,供下次使用。

例項

class Person(object):
  
    def __init__(self, name, age):
        self.name 
= name self.age = age def __new__(cls, name, age): if 0 < age < 150: return object.__new__(cls) # return super(Person, cls).__new__(cls) else: return None def __str__(self): return '{0}({1})'.format(self.__class__.__name__, self.__dict__) print(Person(
'Tom', 10)) print(Person('Mike', 200))

結果:

Person({'age': 10, 'name': 'Tom'})
None

1、__new__方法預設返回例項物件供__init__方法、例項方法使用。

class Foo(object):
    '''黃哥python培訓,黃哥所寫'''
    price = 50

    def how_much_of_book(self, n):
        print(self)
        return self.price * n

foo = Foo()
print(foo.how_much_of_book(8))
print(dir(Foo))

分析上面的程式碼,這個類例項化過程,Foo類繼承object類,繼承了object的__new__方法。

當你沒有重寫這個方法(通俗來說,你沒有在Foo類中沒有定義__new__方法),Foo例項化是預設自動呼叫父類__new__方法,這個方法返回值為類的例項(self),提供這個函式how_much_of_book,預設的第一個引數self。

class Foo(object):
    price = 50

    def __new__(cls, *agrs, **kwds):
        inst = object.__new__(cls, *agrs, **kwds)
        print(inst)
        return inst


    def how_much_of_book(self, n):
        print(self)
        return self.price * n

foo = Foo()
print(foo.how_much_of_book(8))
# <__main__.Foo object at 0x1006f2750>
# <__main__.Foo object at 0x1006f2750>
# 400

請看上面程式碼,Foo類中過載了__new__方法,它的返回值為Foo類的例項物件。

2、__init__ 方法為初始化方法,為類的例項提供一些屬性或完成一些動作。

class Foo(object):

    def __new__(cls, *agrs, **kwds):
        inst = object.__new__(cls, *agrs, **kwds)
        print(inst)
        return inst


    def __init__(self, price=50):
        self.price = price

    def how_much_of_book(self, n):
        print(self)
        return self.price * n

foo = Foo()
print(foo.how_much_of_book(8))

# <__main__.Foo object at 0x1006f2750>
# <__main__.Foo object at 0x1006f2750>
# 400

3、__new__ 方法建立例項物件供__init__ 方法使用,__init__方法定製例項物件。

__new__ 方法必須返回值,__init__方法不需要返回值。(如果返回非None值就報錯)

4、一般用不上__new__方法,__new__方法可以用在下面二種情況。

__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

繼承不可變資料型別時需要用到__new__方法(like int, str, or tuple) 。

class Inch(float):
    "Convert from inch to meter"
    def __new__(cls, arg=0.0):
        return float.__new__(cls, arg*0.0254)

print(Inch(12))

用在元類,定製建立類物件

class MetaClass(type):

    def __new__(meta, name, bases, dct):
        print '-----------------------------------'
        print "Allocating memory for class", name
        print meta
        print bases
        print dct
        return super(MetaClass, meta).__new__(meta, name, bases, dct)

    def __init__(cls, name, bases, dct):
        print '-----------------------------------'
        print "Initializing class", name
        print cls
        print bases
        print dct
        super(MetaClass, cls).__init__(name, bases, dct)


class Myclass(object):
    __metaclass__ = MetaClass

    def foo(self, param):
        print param


p = Myclass()
p.foo("hello")

# -----------------------------------
# Allocating memory for class Myclass
# <class '__main__.MetaClass'>
# (<type 'object'>,)
# {'__module__': '__main__', 'foo': <function foo at 0x1007f6500>, '__metaclass__': <class '__main__.MetaClass'>}
# -----------------------------------
# Initializing class Myclass
# <class '__main__.Myclass'>
# (<type 'object'>,)
# {'__module__': '__main__', 'foo': <function foo at 0x1007f6500>, '__metaclass__': <class '__main__.MetaClass'>}
# hello