簡體   English   中英

functools.partial 類方法

[英]functools.partial on class method

我正在嘗試使用另一個更通用的類方法來定義一些類方法,如下所示:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    red = functools.partial(_color, type='_red')
    blue = functools.partial(_color, type='_blue')
    green = functools.partial(_color, type='_green')

但是當我嘗試調用這些方法中的任何一個時,我得到:

rgb = RGB(100, 192, 240)
print rgb.red()
TypeError: _color() takes exactly 2 arguments (1 given)

我猜 self 沒有傳遞給_color因為rgb.red(rgb)工作。

您正在函數上創建部分,而不是方法。 functools.partial()對象不是描述符,它們本身不會添加self參數,也不能充當方法本身。 只能包裝綁定的方法或函數,它們根本不適用於未綁定的方法。 這是記錄在案

partial對象類似於function對象,因為它們是可調用的、弱可引用的,並且可以具有屬性。 有一些重要的區別。 例如, __name____doc__屬性不是自動創建的。 此外,類中定義的partial對象的行為類似於靜態方法,並且不會在實例屬性查找期間轉換為綁定方法。

改用property s; 這些描述符:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    @property
    def red(self): return self._color('_red')
    @property
    def blue(self): return self._color('_blue')
    @property
    def green(self): return self._color('_green')

從 Python 3.4 開始,您可以在此處使用新的functools.partialmethod()對象 當綁定到一個實例時,它會做正確的事情:

class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    red = functools.partialmethod(_color, type='_red')
    blue = functools.partialmethod(_color, type='_blue')
    green = functools.partialmethod(_color, type='_green')

但是這些必須被調用,而property對象可以用作簡單的屬性。

partialmethod的問題在於它與inspect.signaturefunctools.wraps ,...不兼容。

奇怪的是,如果您使用部分文檔實現示例自己重新實現functools.partial ,它將起作用:

# Implementation from:
# https://docs.python.org/3/library/functools.html#functools.partial
def partial(func, /, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        return func(*args, *fargs, **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc
class RGB(object):
    def __init__(self, red, blue, green):
        super(RGB, self).__init__()
        self._red = red
        self._blue = blue
        self._green = green

    def _color(self, type):
        return getattr(self, type)

    red = partial(_color, type='_red')
    blue = partial(_color, type='_blue')
    green = partial(_color, type='_green')

rgb = RGB(100, 192, 240)
print(rgb.red())  # Print red

原因是newfunc是一個真正的函數,它使用newfunc.__get__實現了描述符協議 type(functools.partial)是一個覆蓋了__call__的自定義類。 類不會自動添加self參數。

暫無
暫無

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

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