簡體   English   中英

在繼承自int或float或str的類中設置參數的值

[英]Set the value of an argument in a class who inherits from int or float or str

當我嘗試設置從str繼承的類的參數的值時,會引發錯誤。 只有當我嘗試使用myClass(arg = 'test')訪問參數時才會發生錯誤。 錯誤是:

TypeError: 'arg' is an invalid keyword argument for this function

問題顯示在此示例中:

class A(str):    
    def __init__(self, arg):
        pass

A("test") # Works well
A(arg = "test") # Fails

只有最后一行才會引發錯誤。 前一行效果很好。 intfloat繼承的類的問題是相同的。

更新(解決方案):

我找到了這些鏈接的解決方案:

解決方案是:

class A(str):

    def __new__(cls, *args, **kwargs):
        return str.__new__(cls)

    def __init__(self, arg01):
        print(arg01)

A(arg01= "test")

我不確切知道為什么會有效,我會對此進行調查。 如果有人有明確的解釋,我很感興趣,我提前感謝他。

更新(我的解釋):

我完全不確定我會說什么,但這就是我的理解。

想象一下沒有任何遺產的班級'myClass' 當我這樣做myInstance = myClass() ,會發生以下情況:

執行myClass.__new__方法。 此方法將創建對象myInstance __new__是真正的構造函數( __init__不是構造函數!)。 在偽代碼中, __new__看起來像這樣:

def __new__ (cls, *args, **kwargs):

    myInstance = # Do some stuff to create myInstance, an object of the type passed as argument (cls).
    # Add the method __init__ to myInstance.
    # Call __init__ and pass to it the list 'args' and the dictionary 'kwargs' (both come from arguments of __new__). Pass to it also the object itself (self) : 
    obj.__init__(self, args, kwargs) :
        # Do some stuff.

當我們使用不可變類型(str,int,float,tuple)時,情況會有所不同。 在之前的偽代碼中,我寫了def __new__(cls, *args, **kwargs) 對於不可變類型,方法__new__的偽代碼__new__是這個def __new__(cls, anUniqueValue) 我並不真正理解為什么immutableTypes.__new__的行為與其他行為不同,但事實並非如此。 你可以在這個例子中看到它:

class foo():

    def __init__(self):
        pass

foo.__new__(foo, arg = 1)
# That works because the method __new__ look like this : def __new__(*args, **kargs).

str.__new__(str, arg = 1)
# That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue).

從那里,我們可以理解為什么之前提出的解決方案有效。 我們所做的是編輯一個不可變類型的方法__new__ ,就像一個可變類型一樣工作。

def __new__(cls, *args, **kwargs):
    return str.__new__(cls)

這兩def __new__ (cls, anUniqueValue)轉換為def __new__ (cls, *args, **kwargs)

我希望我的解釋幾乎清楚,沒有太多錯誤。 如果你說法語,你可以學到更多的鏈接: http://sametmax.com/la-difference-entre- -et- 初始化烯蟒蛇/

你所寫的內容基本上是正確的,這里和那里都有一些錯誤。


class A(str):

    def __new__(cls, *args, **kwargs):
        return str.__new__(cls)

    def __init__(self, arg01):
        print(arg01)

這不完全正確:如果你沒有將任何參數傳遞給str.__new__ ,你的新實例將相當於一個空字符串。

class A(str):

    def __new__(cls, arg):
        return str.__new__(cls, arg)

    def __init__(self, arg):
        print(arg)

通常, __init__ __new____init__應具有相同的簽名。 這不是必需的,但在這種情況下你需要將arg傳遞給str.__new__所以你必須攔截arg


執行myClass.__new__方法。 此方法將創建對象myInstance __new__是真正的構造函數( __init__不是構造函數!)。 在偽代碼中, __new__看起來像這樣:

調用__init__不是__new__的責任,正如這個簡單的例子所示:

class C:

    def __new__(cls):
        print('entering __new__')
        self = super().__new__(cls)
        print('exiting __new__')
        return self

    def __init__(self):
        print('entering __init__')
        super().__init__()
        print('exiting __init__')


C()

# Output:
# entering __new__
# exiting __new__
# entering __init__
# exiting __init__

正如你所看到的,在我的__new__我沒有明確地調用__init__ ,而object.__new__也沒有調用__init__

每當__new__返回該類型的實例時,Python解釋器本身就會自動調用__init__


當我們使用不可變類型(str,int,float,tuple)時,情況會有所不同。

這不完全正確。 當我們從不使用默認__new__實現的類型繼承時 ,情況就不同

默認的__new__實現(即object.__new__ )非常寬松,並忽略每個位置參數和關鍵字參數。 如果用不太寬松的實現替換它,那么就會發生類似你正在觀察的問題。

重要的是要理解的是,問題不是由非默認的__new__本身引起的,而是由於我們的__init____new__不兼容


  foo.__new__(foo, arg = 1) # That works because the method __new__ look like this : def __new__(*args, **kargs). str.__new__(str, arg = 1) # That fails because we are trying to pass the attribute 'arg' to a method which look like this : def __new__(anUniqueValue). 

你說對了。 只有一點是錯的: str.__new__的正確簽名是:

def __new__(cls[, object[, encoding[, errors]]])

cls之外的所有參數都是位置和關鍵字參數。 事實上你可以這樣做:

>>> class C(str):
...     def __init__(self, object):
...         pass
... 
>>> C('abc')
'abc'
>>> C(object='abc')
'abc'

你看? 我們使用了__init__的簽名,它與str.__new__兼容,現在我們可以避免覆蓋__new__

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM