Maybe the title is a bit misleading, however I wanted to create a simple decorator to decorate some class methods as "allowed" in an RPC mechanism, but I'm stuck on a strange error when trying to access class variables (Python 2.7.5). Check the code below:
class myclass():
rpcallowedmethods = []
def __init__(self):
pass
def rpcenabled(fn):
print fn
print globals()
print myclass
#rpcenabled
def somefunc(self,param):
pass
c = myclass()
Exception: NameError: global name 'myclass' is not defined
Anyone can explain the reason behind this to me?
EDIT:
What I'm asking is more about the fact that python executes the decorator defined in a class and run against decorated classmethods even prior having the class in the globals, so I believed it's more of a logical "bug" in the python implementation than a seemingly obvious NameError
The actual class object is only assigned to its name after its definition is finished. Thus you cannot use the class name during its definition. You can either create a decorator outside of the class to which you explicitly pass the list you want to fill, or use the following:
class myclass():
rpcmethods = []
def _rpcallowed(fct, l=rpcmethods):
l.append(fct)
return fct
#_rpcallowed
def myfct(): pass
Note that the default parameter (l=rpcmethods) is a workaround as you cannot access a class variable inside of a function without a reference to the class or an instance.
The variant with the decorator outside of the class would probably qualify as being "cleaner" than this as it's explicit and reusable, but it would be a bit more code and less specific.
You're abusing decorators. A decorator is meant to add something to thing object is given. "decorating" it somehow.
The more usual way to do something like this would be to decorate both the method and the class. Metaclasses are another way to solve this problem. They're more powerful, but are overkill for your current problem. However, directly decorating the functions might be all you need to do. And save collating the rpc functions for when a proxy is made.
from types import FunctionType
def enable_rpc(func):
func.rpc_enabled = True
return func
def rpc_enabled_class(cls):
functions = [attr for attr in vars(cls).values()
if isinstance(attr, FunctionType)]
cls._rpc_enabled_methods = [
func for func in functions
if getattr(func, "rpc_enabled", False)
]
return cls
#rpc_enabled_class
class SampleClass(object):
#enable_rpc
def my_func(self):
pass
print(SampleClass._rpc_enabled_methods)
Strange error?
print myclass
caused the error. You can't use the name myclass in its definition...
Related
I am writing a class for a neural network and I want to give it some form of customization, so that you can choose different cost functions and regularizations. For this I want to set them as default parameters in the __init__() method.
But when I pass MyClass.static_method in my example, the Interpreter then tells me that MyClass is not (yet) defined. Why is this and is there a nicer workaround than mine?
You can of course just set the static method as a default parameter, but then other problems arise. For example, if I want to access the functions name (which I actually want), I cannot use __name__ rightaway. I know how to do it another way, by accessing static_method.__func__.__name__. But this seems clumsy and as you get a staticmethod object, seems like its not intended to be used this way.
class MyClass:
#staticmethod
def static_method():
do_something()
def __init__(self, func=MyClass.static_method, func2=static_method):
self.name = func.__name__ #Does not work
self.name2 = func2.__func__.__name__ #Should work
I did expect for the MyClass.static_method to work, but the class does not seem to exist then. So, one last time, why?
The reason you're having problems with your static method usage as a default argument is due to a combination of two issues.
The first issue is that the default argument needs to be well defined when the def statement is run, not only when the function is called. That's because the default argument gets built into the function object, rather than being recalculated each time the function runs (this is the same reason why a mutable default argument like an empty list is often an error). Anyway, this is why you can't use MyClass.static_method as the default argument, since MyClass isn't defined yet when the function is being defined (the class object is only made after all its contents have been created).
The next issue is that a staticmethod object doesn't have all the same attributes and methods as a regular function. Normally this doesn't matter, as when you access it through a class object (e.g. MyClass.static_method once MyClass exists) or through an instance (e.g. self.static_method), it will be callable and have a __name__. But that's because you get the underlying function in those situations, rather than the staticmethod object itself. The staticmethod object itself is a descriptor, but not a callable.
So neither of these functions will work correctly:
class MyClass:
#staticmethod
def static_method():
pass
def foo(self, func=MyClass.static_method): # won't work because MyClass doesn't exist yet
pass
def bar(self, func=static_method): # this declaration will work (if you comment out foo)
name = func.__name__ # but this doesn't work when the bar() is called
func() # nor this, as func is the staticmethod object
What does work would be to use the actual function underlying the staticmethod object as the default:
def baz(self, func=static_method.__func__): # this works!
name = func.__name__
func()
This also works when you pass in some other function (or bound method), unlike the version of your code that used name = func.__func__.__name__.
DEFAULT = object()
class MyClass:
#staticmethod
def static_method():
do_something()
def __init__(self, func=DEFAULT, func2=DEFAULT):
self.name = self.static_method.__name__ if func is DEFAULT else func.__name__
self.name2 = self.static_method.__func__.__name__ if func2 is DEFAULT else func2.__func__.__name__
I guess??
I wanted to access the class on which method is to be defined. This can be used, for example, to create alias for methods with decorator. This particular case could be implemented without using decorator (alias = original_name), but I would like to use decorator, primarily so because the aliasing will be visible along side the method definition at the top, useful when the method definition is long.
def method_alias(*aliases):
def aliased(m):
class_of_m = ??? # GET class of this method
for alias in aliases:
setattr(class_of_m, alias, m)
return m
return aliased
class Test():
#method_alias('check', 'examine')
def test():
print('I am implemented with name "test"')
Later, I found here that the above could be implemented by using two decorators (first store the aliases as method attributes, later when the class is already created, add the attributes to class). Can it be done without decorating the class, i.e. only decorating the method? This requires getting access to the class name in the decorator.
The short answer is no. The contents of the class body are evaluated before the class object is created, i.e. the function test is created and passed to the decorator without class Test already existing. The decorator is therefore unable to obtain a reference to it.
To solve the problem of method aliasing, I reckon three approaches:
Using a class decorator as described by your link.
Using a metaclass, which lets you modifies the class' __dict__ before the class object is created. (Implementing a metaclass class is acutally overriding the default constructor for class objects, see here. Also the metaclass usage syntax has changed in Python 3.)
Creating the aliases in the __init__ method for each instance of Test.
The first approach is probably the most straightforward. I wrote another example. It basically does the same as your link, but is more stripped down to make it a bit clearer.
def alias(*aliases):
def decorator(f):
f.aliases = set(aliases)
return f
return decorator
def apply_aliases(cls):
for name, elem in list(cls.__dict__.items()):
if not hasattr(elem, 'aliases'):
continue
for alias in elem.aliases:
setattr(cls, alias, elem)
return cls
#apply_aliases
class Test(object):
#alias('check', 'examine')
def test(self):
print('I am implemented with name "test"')
Test().test()
Test().check()
Test().examine()
I'm trying to create a class/static method within a class. I need SignInForm to have the defined instance variables, as they are rendered by Django's template. How does one call a method within a class from an instance variable? My objective is to update each variable with the custom widget for creating a consistent style.
class SignInForm(forms.Form):
#classmethod
def get_text_input_with_attributes():
return forms.TextInput(attrs= {'class':'form-style'})
first_name = forms.CharField(max_length=50,required=True)
first_name.widget = SignInForm.get_text_input_with_attributes()
last_name = forms.CharField(max_length=50,error_messages={'required': ''})
last_name.widget = SignInForm.get_text_input_with_attributes()
....lots of other custom fields
Error:
name 'SignInForm' is not defined
First, the short version:
You can't call methods of a class—even classmethods and staticmethods—while you're in the middle of defining that class, at least not easily.
So, what can you do? Well, really, you don't want a class method or a static method here. You want a regular old function. Like this:
class Spam(object):
def _func():
return 42
class_attr = _func()
del _func
After the class is defined, _func would be an instance method—and an un-callable instance method, since it doesn't take a self. (That's why I prefixed it with an underscore, and also del'd it, to make it harder to accidentally call it later…)
But while it's being defined, it's a normal function, and can be called as such.
I should mention that usually, wanting to do this is a sign that there's something off about your design, and the thing you're trying to write as a classmethod or staticmethod should actually be a method of a base class, or a free function or a class constructor, or maybe even a metaclass method.
As David Sanders' answer explains, the specific thing you're trying to do is common enough that there's an idiomatic way to write it: as a class constructor for a TextField subclass.
How does this work?
Clearly, while you're in the middle of executing the Spam class definition, there is nothing called Spam, so you definitely can't call Spam._func.
But why can you call _func? You have to understand how class definitions are executed. Oversimplifying a bit: Python creates an empty global dictionary, runs all the code inside the class definition as if it were a script, then it goes back to the real globals and runs Spam = type('Spam', (object,), that_global_dict). So when we do class_attr = _func(), we're inside that temporary global environment, and _func is a function in that environment, so we can call it.
So, why can't we do this with a classmethod or staticmethod?
For one thing, you need a cls object to call a classmethod, and we don't have one.
For another, classmethod and staticmethod objects aren't callable. Function objects are callable as themselves, and they're also descriptors that can be used to construct bound methods. Class and static methods are not callable, they're just descriptors that can be used to construct bound methods in special ways (bound to a class or to nothing, instead of to an instance).
So, what if you wanted to write something that was usable as a class-definition-time function, and also as a static method later? The simplest way is:
class Spam(object):
def _func():
return 42
smeth = staticmethod(_func)
class_attr = func()
del _func
A decorator like #staticmethod just does, in effect, _func = staticmethod(_func). We can do the same thing, but give the result a different name, and now we've got a static method, while still having the original function to call directly.
While abernet's answer does a good job of explaining why you were getting that error, the idiomatic way to do this with django would be something like this:
from django import forms
class SignInFormCharField(forms.CharField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('widget', forms.TextInput(attrs={'class': 'form-style'}))
super(SignInFormCharField, self).__init__(*args, **kwargs)
class SignInForm(forms.Form):
first_name = SignInFormCharField(max_length=50, required=True)
last_name = SignInFormCharField(max_length=50, error_messages={'required': ''})
# ...
When you decorate a method, it is not bound yet to the class, and therefor doesn't have the im_class attribute yet. I looking for a way to get the information about the class inside the decorator. I tried this:
import types
def decorator(method):
def set_signal(self, name, value):
print name
if name == 'im_class':
print "I got the class"
method.__setattr__ = types.MethodType(set_signal, method)
return method
class Test(object):
#decorator
def bar(self, foo):
print foo
But it doesn't print anything.
I can imagine doing this:
class Test(object):
#decorator(klass=Test)
def bar(self, foo):
print foo
But if I can avoid it, it would make my day.
__setattr__ is only called on explicit object.attribute = assignments; building a class does not use attribute assignment but builds a dictionary (Test.__dict__) instead.
To access the class you have a few different options though:
Use a class decorator instead; it'll be passed the completed class after building it, you could decorate individual methods on that class by replacing them (decorated) in the class. You could use a combination of a function decorator and a class decorator to mark which methods are to be decorated:
def methoddecoratormarker(func):
func._decorate_me = True
return func
def realmethoddecorator(func):
# do something with func.
# Note: it is still an unbound function here, not a method!
return func
def classdecorator(klass):
for name, item in klass.__dict__.iteritems():
if getattr(item, '_decorate_me', False):
klass.__dict__[name] = realmethoddecorator(item)
You could use a metaclass instead of a class decorator to achieve the same, of course.
Cheat, and use sys._getframe() to retrieve the class from the calling frame:
import sys
def methoddecorator(func):
callingframe = sys._getframe(1)
classname = callingframe.f_code.co_name
Note that all you can retrieve is the name of the class; the class itself is still being built at this time. You can add items to callingframe.f_locals (a mapping) and they'll be made part of the new class object.
Access self whenever the method is called. self is a reference to the instance after all, and self.__class__ is going to be, at the very least, a sub-class of the original class the function was defined in.
My strict answer would be: It's not possible, because the class does not yet exist when the decorator is executed.
The longer answer would depend on your very exact requirements. As I wrote, you cannot access the class if it does not yet exists. One solution would be, to mark the decorated method to be "transformed" later. Then use a metaclass or class decorator to apply your modifications after the class has been created.
Another option involves some magic. Look for the implementation of the implements method in zope.interfaces. It has some access to the information about the class which is just been parsed. Don't know if it will be enough for your use case.
You might want to take a look at descriptors. They let you implement a __get__ that is used when an attribute is accessed, and can return different things depending on the object and its type.
Use method decorators to add some marker attributes to the interesting methods, and use a metaclass which iterates over the methods, finds the marker attributes, and does the logic. The metaclass code is run when the class is created, so it has a reference to the newly created class.
class MyMeta(object):
def __new__(...):
...
cls = ...
... iterate over dir(cls), find methods having .is_decorated, act on them
return cls
def decorator(f):
f.is_decorated = True
return f
class MyBase(object):
__metaclass__ = MyMeta
class MyClass(MyBase):
#decorator
def bar(self, foo):
print foo
If you worry about that the programmer of MyClass forgets to use MyBase, you can forcibly set the metaclass in decorator, by exampining the globals dicitionary of the caller stack frame (sys._getframe()).
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 a way for a class to refer to itself without needing to name itself specifically, hence I want self to work for the class, not just methods/functions. How can I achieve this?
EDIT: The point of this is that I'm trying to refer to the class name from inside the class itself with something like self.class._name_ so that the class name isn't hardcoded anywhere in the class's code, and thus it's easier to re-use the code.
EDIT 2: From what I've learned from the answers below, what I'm trying to do is impossible. I'll have to find a different way. Mission abandoned.
EDIT 3: Here is specifically 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
Note that self is not defined at the time when you want the class to refer to itself for the assignment to work. This is because (in addition to being named arbitrarily), self refers to instances and not classes. At the time that the suspect line of code attempts to run, there is as of yet no class for it to refer to. Not that it would refer to the class if there was.
In a method, you can always use type(self). That will get the subclass of MyClass that created the current instance. If you want to hard-code to MyClass, that name will be available in the global scope of the methods. This will allow you to do everything that your example would allow if it actually worked. E.g, you can just do MyClass.some_attribute inside your methods.
You probably want to modify the class attributes after class creation. This can be done with decorators or on an ad-hoc basis. Metaclasses may be a better fit. Without knowing what you actually want to do though, it's impossible to say.
UPDATE:
Here's some code to do what you want. It uses a metaclass AutoViewConfigMeta and a new decorator to mark the methods that you want view_config applied to. I spoofed the view_config decorator. It prints out the class name when it's called though to prove that it has access to it. The metaclass __new__ just loops through the class dictionary and looks for methods that were marked by the auto_view_config decorator. It cleans off the mark and applies the view_config decorator with the appropriate class name.
Here's 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'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()
Let me know if you have any questions.
Python has an "explict is better than implicit" design philosophy.
Many languages have an implicit pointer or variable in the scope of a method that (e.g. this in C++) that refers to the object through which the method was invoked. Python does not have this. Here, all bound methods will have an extra first argument that is the object through which the method was invoked. You can call it anything you want (self is not a keyword like this in C++). The name self is convention rather than a syntactic rule.
Your method myFunction defines the variable self as a parameter so it works. There's no such variable at the class level so it's erroring out.
So much for the explanation. I'm not aware of a straightforward way for you to do what you want and I've never seen such requirement in Python. Can you detail why you want to do such a thing? Perhaps there's an assumption that you're making which can be handled in another way using Python.
self is just a name, your self in this case is a class variable and not this for the object using which it is called,
self is treated as a normal variable and it is not defined, where as the self in the function comes from the object used for calling.
you want to treat the object reference in self as a class variable which is not possible.
self isn't a keyword, it's just a convention. The methods are attributes of the class object (not the instance), but they receive the instance as their first argument. You could rename the argument to xyzzy if you wanted and it would still work the same way.
But (as should be obvious) you can't refer to a method argument outside the body of the method. Inside a class block but outside of any method, self is undefined. And the concept wouldn't even make sense -- at the time the class block is being evaluated, no instance of the class can possibly exist yet.
Because the name self is explicitly defined as part of the arguments to myFunction. The first argument to a method is the instance that the method was called on; in the class body, there isn't an "instance we're dealing with", because the class body deals with every possible instance of the class (including ones that don't necessarily exist yet) - so, there isn't a particular object that could be called self.
If you want to refer to the class itself, rather than some instance of it, this is spelled self.__class__ (or, for new-style classes in Py2 and all classes in Py3, type(self)) anywhere self exists. If you want to be able to deal with this in situations where self doesn't exist, then you may want to look at class methods which aren't associated with any particular instance, and so take the class itself in place of self. If you really need to do this in the class body (and, you probably don't), you'll just have to call it by name.
You can't refer to the class itself within the class body because the class doesn't exist at the time that the class body is executed. (If the previous sentence is confusing, reading up about metaclasses will either clear this up or make you more confused.)
Within an instance method, you can refer to the class of the instance with self.__class__, but be careful here. This will be the instance's actual class, which through the power of inheritance might not be the class in which the method was defined.
Within a class method, the class is passed in as the first argument, much like 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 might differ due to inheritance.
class OtherClass(MyClass):
pass
OtherClass.foo() # Should print "OtherClass"
If you really need to refer to MyClass within a method of MyClass, you're pretty much going to have to refer to it as MyClass unless you use magic. This sort of magic is more trouble than it is worth.