Python类方法引发AttributeError

4

我有问题在Flask中执行一个类方法。

models/User.py文件中:

from mongoengine import *

class User(Document):
  first_name = StringField()
  last_name = StringField()
  ...

  def __init__(self, arg1, arg2, ...):
    self.first_name = arg1
    self.last_name = arg2
    ...

  @classmethod
  def create(self, arg1, arg2, ...):
    #do some things like salting and hashing passwords...
    user = self(arg1, arg2, ...)
    user.save()
    return user

在主要的应用程序Python文件中:
from models import User
...
def func():
  ...

  #Throws "AttributeError: type object 'User' has no attribute 'create'"
  user = User.create(arg1, arg2, ...) 

我能否在不实例化User对象的情况下调用User类上的create方法?我使用的是Python 2.7.2,也尝试了使用非装饰器语法:create = classmethod(create),但没成功。提前谢谢!编辑:我发现了一个问题:models文件夹中没有包含__init__.py文件,因此它不是一个模块,所以from models import User实际上没有导入我想要的文件。之前并未出现错误,是因为我曾经在应用程序python脚本的同一目录下有一个models.py模块,但删除后我从未删除相应的.pyc文件。现在,我收到的错误是AttributeError: 'module' object has no attribute 'create',而不是之前的错误,但我确信现在已经导入了正确的文件。编辑2:问题解决了。我将导入代码更改为from models.User import User,现在它可以调用方法了。

1
User(arg1, arg2, ...): #constructor是什么?我认为这不是有效的Python语法。 - Joel Cornett
在编程之前,你必须阅读文档! - Dmitry Zagorulkin
1
尝试发布一个最小但完整的代码示例,实际展示你遇到的问题。你所做的是解释你的代码,引入了新的错误,并使人们无法帮助你。 - Duncan
是的,抱歉我写这篇文章时很累,回头看我所写的内容,它毫无意义。我编辑了这篇文章,以更准确地反映我的代码。 - osdiab
2个回答

3
问题有两个方面:
  1. User.py文件位于models/文件夹中,这意味着我的导入实际上是在models.py文件中查找User类,但该文件已经不存在了, 但由于models.pyc文件仍然存在而没有报错。
  2. 在目录内部进行导入时,导入方式不正确。应该使用from models.User import User,只要models/文件夹是一个模块,那么我所需要的就是touch models/__init__.py

2
很棒,这很有道理,而且它为我节省了相当多的时间,因为我也遇到了关于停滞pyc文件的同样问题。你完全正确地捍卫了你的问题,并澄清了你已经查看了明显的解决方案。 - Milimetric
1
是的,“阅读文档”并不是一个很有帮助的答案——如果我没有必要,我也不会在 Stack Overflow 上提问! :) - osdiab

1
>>> class foo(object):
...     def __init__(self):
...             pass
...     @classmethod
...     def classmethod(cls):
...             return 0
...
>>> a = foo()
>>> a.classmethod()
0
>>>

抱歉,我的问题写得很糟糕。虽然已经完成了,但类方法仍然无法正常工作。 - osdiab
@OmarDiab 如果你使用classmethod装饰器,你的第一个参数应该是cls而不是self。http://docs.python.org/library/functions.html#classmethod - Dmitry Zagorulkin
我尝试使用cls和self,但两者都给了我相同的错误。我阅读了相关文档,但不知道我的代码哪里出错了。这就是为什么我在Stack Overflow上提问的原因。如果我的问题有冒犯之处,请见谅,但我在这里提问是因为我不知道自己偏离了文档的哪些内容,而你的无礼并没有帮助我解决任何问题。如果有用的话,我写的是关于通用Foo和Bar类的代码,没有依赖其他模块,它确实可以工作。所以我想继续尝试,但如果有人有更好的见解,我很乐意听取。 - osdiab
@ZagorulkinDmitry 使用 cls 而不是 self 对于遵循惯例非常重要,但这并不能解释错误。此外,您的示例具有非传统的大小写和缩进,并且没有说明使用 cls 的情况。 - duozmo

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