where should I define functions that i use in __init__ - python

I'm writing a class that makes use of some functions inside its __init__ function and I'm not sure about the best practice of where to define those functions. I usually like to define __init__ first but if I need to use the a function/method within the __init__ then it needs to be defined first. I dont want to define it outside the class as its useless outside the class but it seems messy to me to define methods before the __init__. What are the normal conventions for this?

Just add the methods to your class like every other method
class Test(object):
def __init__(self):
self.hi()
def hi(self):
print "Hi!"
No problem at all.
While it is not mentioned in the Python Style Guide IIRC, it's convention to let __init__ be the first method in your class.

The normal convention is indeed to put __init__ before other methods. The reason this works is that functions aren't evaluated until invoked. From the Python docs:
A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object (a wrapper around the executable code for the function). This function object contains a reference to the current global namespace as the global namespace to be used when the function is called.
The function definition does not execute the function body; this gets executed only when the function is called.

It's better to define __init__ function as first function, and you can call functions defined after __init__ inside it.
class A:
def __init__(self):
print self.x()
def x(self):
return 10

Why should it be 'messy' to define methods after the init ? Think about it that way :
When you define
class MyClass(object):
def __init__(self):
self.something = whatever
self.do_something_else()
def do_something_else(self):
...
__init__ is a method of your MyClass class, just like do_something is; it's just the first method of the class that will be called when you create an instance of MyClass. So, putting __init__ first is not only customary but also logical.
Your do_something_else method doesn't have to be defined first because you use it in __init__. From the point of view of MyClass, it's a method like another. When you create your myclass=MyClass() instance, do_something_else has already been defined...

Related

Why does a method within a class work even if not marked with #classmethod or #staticmethod?

I'm new to Python and just learning about its implementation of objects/classes. I understand the difference between an instance method, class method, and static method, I think, but what I don't understand is why a method that has not been decorated as a #classmethod or #staticmethod can be called from the class itself.
My very (very) basic example:
class TestClass:
def __init__(self):
pass
#staticmethod
def print_static_stuff(stuff):
print(stuff)
def print_stuff(stuff):
print(stuff)
TestClass.print_stuff("stuff") # prints "stuff"
TestClass.print_static_stuff("static stuff") # prints "static stuff"
The method print_stuff() seems to act as a static method when called on the class, taking the argument as it's single parameter and not the class (cls). Why can the method not decorated with #staticclass be called on the class? Is this by design or just a weird side-effect, and why? From what I've learned so far, Python, by design, has few to no "weird side-effects".
The first parameter being named self is merely a convention. The instance will be passed as the first positional argument independent of what you've named it (in this case you've called it stuff).

How to use self parameter, #staticmethod keyword inside a class and its methods

I have a python class which has multiple methods. I have defined my methods via #staticmethod instance and I want to call other methods of my class from inside my main function(main_function). I think I need self parameter for calling my other functions from my main function and I want to pass this parameter to my main_function when I create an instance of my class.
class myclass:
#staticmethod
def function1(param1)
print "function1"
#staticmethod
def main_function(self, param1)
function1(param1)
my_object = myclass()
my_object.main_function(param1)
I got this error:
TypeError: main_function() takes exactly 2 arguments (1 given)
The problem is that I have not self parameter when I create my instance. I tried to remove #staticmethod keyword from my method definition and remove all self parameter using, but this does not work.
Only use #staticmethod if you are creating a function that you'd normally want to tie to specific classes but do not need any other context. For example, the str.maketrans() function is a static method because it is a utility function you'd often use when working with strings, namespacing it to the already-existing str type (which pre-exists as a class) makes sense there.
You appear to be using classes as a namespace instead. Don't do that. Use a module for your functions, and you don't have to worry about the special scoping rules that apply to classes. Only use a class when you need to bundle state with functionality.
If you insist on using classes with static methods anyway, you are stuck with hardcoding the class name everywhere:
class myclass:
#staticmethod
def function1(param1)
print "function1"
#staticmethod
def main_function(param1)
# Want to use other functions in this class? Then you will
# have to use the full name of the class as a prefix:
myclass.function1(param1)
You could make use of classmethods instead so you have a reference to the class object:
class myclass:
#staticmethod
def function1(param1)
print "function1"
#classmethod
def main_function(cls, param1)
# Now you can use the `cls` reference to access other attributes
cls.function1(param1)
This has the added advantage that you can use inheritance.
However, using a module is the correct way to organise a set of functions into a namespace. Put everything into a my_module.py file in your package, and use importing;
import my_module
my_module.main_function(param1)
Now all globals in my_module are bundled into one module object, and no prefixing or cls references are needed.

Decorator "template" for class methods can't be a class method?

I have a hierarchy of classes with a whole bunch of similar methods that I've managed to factor out the common parts of using a closure and a decorator:
def makemethod(kernel_method, output_class):
def closure(self, start, end):
set().up()
common()
stuff()
result = []
for i in range(start, end):
args = more().standard().stuff()
result.append(kernel_method(self, args))
finish().up()
return output_class(result)
return closure
def mymethod(output_class):
def decorator(kernel_method):
return makemethod(kernel_method, output_class)
return decorator
Each method that follows the pattern, whether it's a method defined in the base class or a derived class, just has to define its "kernel" and use the decorator to wrap it in the common code:
#mymethod(Class1)
def a_method_that_builds_a_Class1(self, args):
# just the kernel!
#mymethod(Class2)
def a_method_that_builds_a_Class2(self, args):
# just the kernel!
#mymethod(Class2)
def a_different_way_to_build_a_Class2(self, args):
# just the kernel!
All of this works beautifully and does exactly what I want it to. The only problem is, to make it work I've had to define the makemethod function and its decorator wrapper outside of my base class, as module-level functions, and that seems awfully weird to me (though maybe in Python it's not weird at all?)
The inner function closure makes absolutely no sense except as a method of my class (the "common stuff" it does uses all kinds of class attributes), so the outer function that it's defined inside should be a class member, right? But if I try to make the outer functions static or class methods of my base class, I can use them to decorate methods of derived classes, but I can't call them in the base class itself, because inside a class's definition its own name isn't in scope yet. And my base class does have methods that need decorating.
I suppose I could put the closure and decorator in a class on their own, and have my "base" class inherit from that class. Is that what I should do, or is it stylistically okay in Python for closure/decorator "templates" for methods to be module-level functions?

Python class not in globals when using decorator

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...

Why does "self" outside a function's parameters give a "not defined" error?

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.

Categories

Resources