调用元类基类时出错:函数()参数1必须是代码,而不是字符串。

59

我今天早些时候尝试继承threading.Condition类,但没有成功。当我尝试继承threading.Condition类时,下面是Python解释器的输出:

>>> import threading
>>> class ThisWontWork(threading.Condition):
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    function() argument 1 must be code, not str

可以有人解释一下这个错误吗?谢谢!

4个回答

95

你收到那个异常是因为,尽管其名字像类,threading.Condition 实际上是一个函数,而你无法对函数进行子类化。

>>> type(threading.Condition)
<type 'function'>

这个不太有用的错误信息已经在Python缺陷跟踪器上被提出,但它已被标记为“不会修复”。


奇怪,我没有想到去检查它的类型。文档似乎有点误导,因为它们说(http://docs.python.org/library/threading.html) "class threading.Condition([lock])",这似乎有点引人误解。无论如何,感谢您澄清这个问题 :)。 - David Underhill
1
当错误地将模块用作基类时,我也会看到它:class Command(main.cmdroot.list.hosts),而不是正确的Command(main.cmdroot.list.hosts.Command)。 - FDS
3
另一个常见的原因是从一个具有装饰器的基类派生。装饰器也可能会将基类的类型更改为 type <'function'> - Freek Wiekmeijer
有时候我会不小心写成 def MyClass 而非 class MyClass,这会导致同样的错误(还有其他错误)。 - Florian Brucker
1
你不能对函数进行子类化 - 感谢您对此给出明确的答案。我希望错误消息能够说得更清楚。 - Jarad

31
与 OP 遇到的问题不同,但如果您尝试从模块而不是类继承(例如,您尝试从 My.Module 而不是 My.Module.Class 继承),则也可能出现此错误。感谢 这篇文章 帮助我解决了这个问题。
对于这个错误,答案是您可能将一个 Python 类命名为与所在模块(即文件)相同的名称。然后,您导入该模块并尝试像使用类一样使用它。您之所以这样做,可能是因为您不久前还是 Java 程序员,就像我一样 :-)。修复它的方法是导入模块.class 而不仅仅是模块。或者为了清晰明了起见,更改类或模块的名称。

1
当您尝试从def MyClass(object)而不是从class MyClass(object)进行子类化时 - user5359531

29

关于子类化模块,如果您在一个名为Foo.py的文件中定义了类Foo,则这是一个非常容易犯的错误。

当您在另一个文件中创建Foo的子类时,您可能会意外地执行以下操作(这是尝试对模块进行子类化并将导致错误的操作):

import Foo
class SubclassOfFoo(Foo):

当你真的需要做两件事中的任意一件时:

from Foo import Foo
class SubclassOfFoo(Foo):

或者:

import Foo
class SubclassofFoo(Foo.Foo):

4
不要将模块命名为类的一个很好的理由 :) - Anentropic
是的,这对我有用,我的模型和类名相同。 - Joe
当你继承时,有时候因为太累而看不到自己打成了 def(而不是 class),这种情况也可能发生。 - scharfmn

2
遇到了同样的问题。最终通过仔细查看代码解决了这个问题,这就是导致TypeError错误出现的原因,它警告说是字符串而不是代码。
Class Class_name(models.model): //(gives a TypeError of 'str' type) 

"

"
Class Class_name(models.Model): // is the correct one. 

注意,这个特定的错误是由于代码中的一个小写字母 "Model" 而导致的,这使它成为了一个字符串。


这反过来使它成为一个字符串,在Python中小写单词不会自动成为字符串。 - sezanzeb

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