Why does the "I" outside the function parameters give an "undefined" error?

Take a look at this code:

class MyClass(): # Why does this give me "NameError: name 'self' is not defined": mySelf = self # But this does not? def myFunction(self): mySelf2 = self 

Basically, I want the class to be able to refer to itself without calling itself specifically, so I want me to work on the class, and not just using methods / functions. How can I achieve this?

EDIT:. The thing is, I'm trying to refer to the class name inside the class itself with something like self. class ._ name_, so the class name is not hardcoded anywhere in the class code, and therefore it is easier to reuse the code.

EDIT 2: From what I learned from the answers below, what I'm trying to do is impossible. I need to find another way. Mission abandoned.

EDIT 3: Here's exactly what I'm trying to do:

 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 
+3
source share
6 answers

Note that self not defined at the time you want the class to refer to itself for the job to work. This is because (in addition to being named arbitrarily), self refers to instances, not classes. While the suspicious line of code is trying to run, there is as yet no class for it. Not that it applied to the class if it was.

In a method, you can always use type(self) . This will result in a subclass of MyClass that created the current instance. If you want to hardcode the MyClass code, this name will be available in the global scope of the methods. This will allow you to do whatever your example allows, if it really works. For example, you can just do MyClass.some_attribute inside your methods.

You will probably want to change the attributes of the class after creating the class. This can be done using decorators or on a one-time basis. Metaclasses may be better suited. Not knowing what you really want to do is impossible to say.

UPDATE:

Here is the code you want to do. It uses the AutoViewConfigMeta metaclass and a new decorator to mark the methods to which you want to apply view_config . I faked the view_config decorator. He prints out the class name when he calls it to prove that he has access to it. The __new__ __new__ simply scrolls through the class dictionary and searches for methods marked by the auto_view_config decorator. It clears the label and applies the view_config decorator with the corresponding class name.

Here is the code.

 # 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 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() 

Let me know if you have any questions.

+5
source

Python has the concept of "explicit is better than implicit."

Many languages ​​have an implicit pointer or variable in the scope of the method, which (for example, this in C ++) refers to the object through which the method was called. Python doesn't have that. Here, all related methods will have an additional first argument, which is the object through which the method was called. You can call it anything ( self not a keyword like this in C ++). The name self is conditional rather than syntactic.

Your myFunction method defines the self variable as a parameter for it to work. There is no such variable at the class level that it fails.

So much to explain. I don't know an easy way to do what you want, and I have never seen such a requirement in Python. Can you explain why you want to do this? Perhaps there is an assumption that you are doing something that can be handled differently using Python.

+1
source

self is just a name, your self in this case is a class variable, not for the object with which it is called,

self considered a normal variable and is not defined where, when the self function in the function comes from the object used to call it.

you want to treat the object reference in self as a class variable, which is not possible.

+1
source

self not a keyword, it is just an agreement. Methods are attributes of an object of a class (not an instance), but they receive an instance as the first argument. You can rename the argument to xyzzy if you want, and it will work differently.

But (as should be obvious) you cannot refer to a method argument outside the method body. Inside the class block, but outside of any method, self is undefined. And the concept doesn’t even make sense - during the evaluation of the class block, an instance of the class does not exist yet.

0
source

Because the name self explicitly defined as part of the arguments to myFunction . The first argument to a method is an instance of a method call; there is no “instance we are dealing with" in the class of the class because the body of the class deals with all possible instances of the class (including those that do not exist yet) - so there is no concrete object that could be called self .

If you want to refer to the class itself, and not to any instance, it is written self.__class__ (or for new-style classes in Py2 and all classes in Py3, type(self) ) anywhere self exists. If you want to deal with this in situations where self does not exist, you can look at class methods that are not associated with any particular instance, so take the class itself instead of self . If you really need to do this in a class (and probably not), you just need to call it by name.

0
source

You cannot refer to the class itself inside the body of the class, because the class does not exist at the time the class body is executed. (If the previous sentence is confusing, reading about metaclasses will either clear this or make you more confused.)

Inside the instance method, you can access the instance class using self.__class__ , but be careful. This will be the actual instance class, which by degree of inheritance may not be the class in which the method was defined.

In a class method, the class is passed as the first argument, just as instances are the first argument to instance methods:

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

As with instance methods, the actual class may differ due to inheritance.

 class OtherClass(MyClass): pass OtherClass.foo() # Should print "OtherClass" 

If you really need to reference MyClass in the MyClass method, you pretty much have to refer to it as MyClass unless you use magic. This kind of magic has more problems than it costs.

0
source

Source: https://habr.com/ru/post/912566/


All Articles