繁体   English   中英

为什么函数参数之外的“self”会给出“未定义”的错误?

[英]Why does “self” outside a function's parameters give a “not defined” error?

看看这段代码:

class MyClass():

    # Why does this give me "NameError: name 'self' is not defined":
    mySelf = self

    # But this does not?
    def myFunction(self):
        mySelf2 = self

基本上我想要一个类来引用自己而不需要专门命名自己的方法,因此我希望自己为类工作,而不仅仅是方法/函数。 我怎样才能做到这一点?

编辑:这一点是我试图从类内部引用类名称与self之类的东西。 class ._ name _这样类名在代码的任何地方都没有硬编码,因此重用代码更容易。

编辑2:从我从下面的答案中学到的,我想要做的是不可能的。 我必须找到一种不同的方式。 任务放弃了。

编辑3:这是我正在尝试做的事情:

class simpleObject(object):
    def __init__(self, request):
        self.request = request

@view_defaults(renderer='string')
class Test(simpleObject):

    # this line throws an error because of self
    myClassName = self.__class__.__name__

    @view_config(route_name=myClassName)
    def activateTheView(self):
        db = self.request.db
        foo = 'bar'

        return foo

请注意,当您希望类引用自身以使赋值工作时,不会定义self 这是因为(除了被任意命名), self指的是实例而不是类。 在可疑的代码行试图运行的时候,还没有类可以引用它。 不,它引用类,如果有。

在方法中,您始终可以使用type(self) 这将获得创建当前实例的MyClass的子类。 如果要对MyClass进行硬编码,则该名称将在方法的全局范围内可用。 这将允许您执行示例在实际工作时允许的所有内容。 例如,您可以方法中执行MyClass.some_attribute

您可能希望创建类之后修改类属性。 这可以通过装饰器或临时基础来完成。 元类可能更适合。 虽然不知道你真正想做什么,但这是不可能的。

更新:

这里有一些代码可以做你想要的。 它使用元类AutoViewConfigMeta和一个新的装饰器来标记您希望view_config应用于的方法。 我欺骗了view_config装饰器。 它会在调用时打印出类名,以证明它可以访问它。 元类__new__只循环遍历类字典并查找由auto_view_config装饰器标记的方法。 它清除没谱,并应用view_config 适当的类名装饰。

这是代码。

# This just spoofs the view_config decorator.
def view_config(route=''):
    def dec(f):
        def wrapper(*args, **kwargs):
            print "route={0}".format(route)
            return f(*args, **kwargs)
        return wrapper
    return dec

# Apply this decorator to methods for which you want to call view_config with 
# the class name. It will tag them. The metaclass will apply view_config once it 
# has the class name. 
def auto_view_config(f):
    f.auto_view_config = True
    return f

class AutoViewConfigMeta(type):
    def __new__(mcls, name, bases, dict_):
        #This is called during class creation. _dict is the namespace of the class and
        # name is it's name. So the idea is to pull out the methods that need
        # view_config applied to them and manually apply them with the class name.
        # We'll recognize them because they will have the auto_view_config attribute
        # set on them by the `auto_view_config` decorator. Then use type to create
        # the class and return it.

        for item in dict_:
            if hasattr(dict_[item], 'auto_view_config'):  
                method = dict_[item]
                del method.auto_view_config # Clean up after ourselves.
                # The next line is the manual form of applying a decorator.
                dict_[item] = view_config(route=name)(method)  

        # Call out to type to actually create the class with the modified dict.
        return type.__new__(mcls, name, bases, dict_)


class simpleObject(object):
    __metaclass__ = AutoViewConfigMeta 


class Test(simpleObject):

    @auto_view_config
    def activateTheView(self):
        foo = 'bar'

        print foo

if __name__=='__main__':
    t = Test()
    t.activateTheView()

如果您有任何疑问,请告诉我。

Python有一个“明显比隐含更好”的设计理念。

许多语言中具有方法,该方法的范围的隐式指针或变量(例如this其是指通过调用该方法的对象在C ++)。 Python没有这个。 这里,所有绑定方法都将有一个额外的第一个参数,该参数是调用该方法的对象。 你可以称它为任何你想要的( self不是像关键字this在C ++中)。 名称self是约定而不是语法规则。

你的方法myFunction将变量self定义为参数,因此它可以工作。 在班级没有这样的变量,所以它出错了。

这么多的解释。 我不知道你做你想做的直接方式,我从来没有在Python中看到过这样的要求。 你能详细解释为什么要做这样的事吗? 也许假设您正在制作哪些可以使用Python以另一种方式处理。

self只是一个名字,在这种情况下你的self是一个类变量而不是用于调用它的对象,

self被视为一个普通变量,并且没有定义,因为函数中的self来自用于调用的对象。

您希望将self的对象引用视为不可能的类变量。

self不是关键字,它只是一种约定。 这些方法是类对象(不是实例)的属性,但它们将实例作为第一个参数接收。 如果你愿意,可以将参数重命名为xyzzy ,它仍然可以以相同的方式工作。

但是(显而易见)你不能引用方法体外的方法参数。 class块内,但在任何方法之外, self是未定义的。 这个概念甚至没有意义 - 在评估class块时,还没有可能存在类的实例。

因为名称self被明确定义为myFunction参数的一部分。 方法的第一个参数是调用该方法的实例; 在类体中,没有“我们正在处理的实例”,因为类主体处理类的每个可能的实例(包括那些不一定存在的实例) - 所以,没有可称为self特定对象。

如果你想引用类本身 ,而不是它的一些实例,那么拼写为self.__class__ class__(或者,对于Py2中的新式类和Py3中的所有类, type(self)self存在。 如果您希望能够在存在self情况下处理此问题,那么您可能希望查看与任何特定实例无关的类方法 ,因此请使用类本身代替self 如果你真的需要在类体中这样做(并且你可能没有),你只需要按名称调用它。

您不能在类主体中引用类本身,因为在执行类主体时类不存在。 (如果前面的句子令人困惑,那么阅读有关元类的内容将会清除它或者让你更加困惑。)

在实例方法中,您可以使用self.__class__引用实例的类,但请注意这里。 这将是实例的实际类,它通过继承的力量可能不是定义方法的类。

在类方法中,类作为第一个参数传入,就像实例是实例方法的第一个参数一样:

class MyClass(object):
    @classmethod
    def foo(cls):
        print cls.__name__

MyClass.foo() # Should print "MyClass"

与实例方法一样,实际类可能因继承而不同。

class OtherClass(MyClass): 
    pass

OtherClass.foo() # Should print "OtherClass"

如果你真的需要参考MyClass的方法中MyClass ,你几乎将不得不把它称为MyClass ,除非你使用魔法。 这种魔法比它的价值更麻烦。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM