Python混合类 - 未解决的属性引用[PyCharm]

30

我正在使用一个mixin将一系列功能分离到不同的类中。这个mixin只能与唯一的子类混合:

class Mixin:
    def complex_operation(self):
        return self.foo.capitalize()

class A(Mixin):
    def __init__(self):
        self.foo = 'foo'

在我的方法中,Mixin.complex_operation PyCharm 提示 'Unresolved Attribute Reference foo'。

我是否正确地使用了 mixin 模式?是否有更好的方法?(我希望在我的 mixins 中拥有类型提示和自动补全,并且我想要有多个 mixins。)


我复制并粘贴了你的代码,而且 print(A().complex_operation()) 输出了 "Foo"。我们是否需要看到更多的代码?至于更好的方法,继承对于 mixins 是可以的,类型提示和自动补全则完全取决于您选择的 IDE。 - Levi Lesches
是的,它可以工作 - 但正如所提到的,IDE会抱怨并且我没有自动完成... - ikamen
你使用的是哪个集成开发环境?它不应该在函数中评估变量,因为即使 Python 也不会这样做——正是出于这个原因。 - Levi Lesches
我正在使用PyCharm。它确实会检查我是否使用了现有的变量,但是当然,即使它怀疑存在问题,它也会让我执行代码。 - ikamen
那么,这真的是一个mixin吗?按照定义,mixins是模块化的,可以添加到任何类中以扩展功能。我理解想要有更清晰的代码,但在这里添加mixins是不必要且令人困惑的。complex_operation应该是A的一个方法。 - Levi Lesches
显示剩余4条评论
3个回答

22

在Mixin中声明必要的字段,例如:

class Mixin:
    foo: str

    def complex_operation(self):
        return self.foo.capitalize() 

这种方式 mixin 实际上声明了一个类必须拥有哪些字段才能使用该 mixin。类型提示将会在扩展类将不兼容的类型放到声明字段中时生成警告。

编辑:根据 @valex 的建议,用 foo:str 替换了 foo = None。


7

我看到有几个选项。

1) 类型注释(我认为这是最清晰的解决方案):

class Mixin:
    foo: str

    def complex_operation(self):
        return self.foo.capitalize()

2) 默认值 None (@ikamen选项):


class Mixin:
    foo = None

    def complex_operation(self):
        return self.foo.capitalize()

3) 抑制类或特定行的未解决引用错误(我认为这比前两种方法更不规范):

# noinspection PyUnresolvedReferences
class Mixin:
    def complex_operation(self):
        return self.foo.capitalize()

class Mixin:
    def complex_operation(self):
        # noinspection PyUnresolvedReferences
        return self.foo.capitalize()

1
我认为类型注释比None更加严格。我也将它放入了我的答案中。 - ikamen
1
类型注释版本是否将类变量foo设置为值"",还是仅仅是一个声明?如果您期望有一个方法,那么这该怎么做呢? - Minix
@Minix类型注释只是一种声明。 - valex

3

为了让大家更好地理解,我将评论中的想法总结如下:问题在于需要在分离功能的同时保持两个类之间的内在联系。以下是我的解决方案:

1)创建一个模块

创建另一个文件,比如mixin.py,其中包含complex_operation函数。该函数不再接受self参数,而是接受一个字符串:

# mixin.py

def complex_operation (foo: str) -> str: return foo.capitalize()

# main.py

from ai import complex_operation
class A: 
    def __init__(self): self.foo = "foo"
print (complex_operation (A().foo))

2) 将一个类作为参数传递给另一个类

Mixin__init__函数中,添加一个参数来接收A,然后在它的方法中使用:

# mixin.py

class Mixin: 
    def __init__(self, a: A): self.a = a
    def complex_operation(self): return self.a.foo.capitalize()

# main.py

from mixin import Mixin
class A:
    def __init__(self): self.foo = "foo"

print (Mixin (A()).complex_operation())

我喜欢模块解决方案,适用于某些情况。应该记住这种可能性。 - ikamen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接