如何将命名关键字参数添加到函数签名中

时间:2016-10-12 06:49:22

标签: python oop

我可以使用mixin类将base关键字添加到基类函数的签名中吗?目前我无法弄清楚如何避免覆盖基本功能的签名:

from inspect import signature

class Base(object):
    def __init__(self, foo='bar', **kwargs):
        pass

class Mixin(base):
    def __init__(self, foo2='bar2', **kwargs):
        super(Mixin, self).__init__(**kwargs)

class P(Mixin, Base):
    pass

print(signature(P.__init__))


# Output: (self, foo2='bar2', **kwargs)

$ Desired output: (self, foo1='bar1', foo2='bar2', **kwargs)

编辑感谢您到目前为止的答案,遗憾的是我实际上需要将命名参数添加到函数签名中,同时还保留原始基本函数签名中的命名参数(这些参数会因在基地)。原因是signature is used elsewhere for intraspection to extract the parameter names.:这在__init__方法中是否可行?

这是一个(可怕的)部分解决方案,它改变了实例上的签名,但没有更改类本身,也因为某些原因缺少**kwargs

class Mixin(Base):
     def __init__(self, foo2='bar2', **kwargs):
         super(Mixin, self).__init__(**kwargs)
         sig = signature(super(Mixin, self).__init__)
         params = {k:v.default for k,v in sig.parameters.items() if v.default != _empty}
         params['foo2'] = 'bar2'
         argstring = ",".join("{}='{}'".format(k,v) for k,v in params.items())
         exec("def new_init({}, **kwargs): self.__init__(**kwargs)".format(argstring))
         self.__init__ = new_init


class P(Mixin, Base):
    pass

p = P()
print(signature(p.__init__))
# (foo2='bar2', foo='bar')

2 个答案:

答案 0 :(得分:0)

在子类化时,您可以扩展或覆盖超类的方法,但是您不能直接修改它们。通过简单地编写一个同名的新方法来实现覆盖;扩展是通过重写方法然后调用超类的方法作为替换的一部分来实现的。

这是两个类,第二个类重写一个方法并扩展另一个方法:

class A:
    def method1(self):
        print("Method A.1 called")
    def method2(self, arg1):
        print("Method A.2 called with argument", arg1)

class B(A):
    def method1(self):
        print("Method B.1 called")
    def method2(self, arg1, arg2="keyword arg"):
        print("Method B.1 called with arg1=", arg1, "arg2=", arg2)
        super().method2(arg1)
        print("Extended method complete")

在交互式上下文中使用它我们会看到以下内容:

>>> b = B()
>>> b.method1()
Method B.1 called
>>> b.method2("first", arg2="second")
Method B.1 called with arg1= first arg2= second
Method A.2 called with argument first
Extended method complete

*技术上它在Python中是可能的,但是代码会很丑陋,无论如何,使用超类的所有内容都会看到对超类的任何更改。

答案 1 :(得分:0)

@jonrsharpe在评论中回答了这个问题,但是如果你想要一个参数,你可以用mixin的方法进行动态检查:

class Base(object):
    def __init__(self, foo='bar', **kwargs):
        pass

class Mixin(base):
    def __init__(self, **kwargs):
        kwargs.pop('required_param')
        kwargs.pop('optional_param', None)
        super(Mixin, self).__init__(**kwargs)

class P(Mixin, Base):
    pass