Function in a python class that is not a method - python-2.7

I have a class that needs auxiliary functions, e.g. one to calculate a checksum that just uses the passed in arguments and not any properties of the class. This function is only called by the class's methods. So I dont need to pass in the 'self' as the first formal of the function.
How should I implement these functions? Can I have non-method functions in a class? Should I define them outside the class (even though they are not used by anything else)? Or is it ok for them to be regular methods?

If you want a function inside a class that doesn't take self as an argument, use the #staticmethod decorator:
class Awesomeness(object):
def method(self, *args):
pass
#staticmethod
def another_method(*args):
pass
However, from a conceptual standpoint I would definitely consider putting it at module scope, especially if it's a checksum function that doesn't use instance or class properties.

Just do a nested function:
class Foo(object):
def bar(self, arg):
def inner(arg):
print 'Yo Adrian imma in inner with {}!'.format(arg)
inner(arg)
Foo().bar('argument')
Or just ignore the self:
class Foo(object):
def prive(_, arg):
print 'In prive with {}!'.format(arg)
def bar(self, arg):
def inner(arg):
print 'Yo Adrian imma in inner with {}!'.format(arg)
inner(arg)
self.prive(arg)
def foo(self,arg):
self.prive(arg)
Foo().bar('argument')
Foo().foo('another argument')
Second example prints:
Yo Adrian imma in inner with argument!
In prive with argument!
In prive with another argument!

tldr define a function outside the class
class myclass():
def __init__(self):
myfunc()
def myfunc():
print('f')
myclass() # prints f
from best to worst:
define outside the class
use staticmethod decorator
define a method, but ignore self
the disadvantage of 2 & 3 is that the "function" is still a method as it can applied to an object the regular way: self.myfunc()

Related

abstractproperty + classmethod decorators in python

I want to enforce childrens to use a classmethod in python2.7.
I tried this:
import abc
class Base(object):
__metaclass__ = abc.ABCMeta
#abc.abstractproperty
def value(self):
pass
#abc.abstractproperty
#classmethod
def text(cls):
pass
class Imp(Base):
TEXT = "hi im text"
#classmethod
def haba(cls):
print 'HI'
#property
def value(self):
return 'asdasd'
#classmethod
#property
def text(cls):
return 'ho ho p'
print Imp.text
print Imp.TEXT
But I'm getting this output:
<bound method ABCMeta.? of <class 'main.Imp'>>
hi im text
How I can properly enforce childrens to implement classmethod properties?
You can see that Imp.TEXT is working but there is no way to enforce creating this member from base class this way
After re-reading your question a few times I concluded that you want the cl method to behave as if it is a property for the class.
First, Python's implementation of abstract method/property checking is meant to be performed at instantiation time only, not at class declaration. I hope you are aware of that.
Second, Python's descriptor protocol allows for the creation of the equivalent of "class properties", although there is no higher level support for that on the language itself - you can create a class which __get__ method returns your calculated property when the instance argument is None (usually descriptors will return 'self' so that they can be retrieved from the class).
Finally - it is possible that by declaring a custom metaclass being abstract itself, and then declaring it as your class metaclass, abstractproperties will trigger in runtime - let's try that - :
In [1]: import abc
In [2]: class AbsPropertyMeta(abc.ABC, type):
...: #abc.abstractproperty
...: def cl(cls):
...: return "Ho ho ho"
...:
In [3]: class ConcreteExample(metaclass=AbsPropertyMeta):
...: pass
...:
(Note that I will develop the answer using Python 3, which should be what you should be using in any new project or for learning purposes as well)
So, as for the former example, the property in the metaclass does work as a "class property", but Python does not enforce its redefinition in the class body.
So, if you really need this design, you should create a complete custom metaclass for that, and let go of the abc.ABCMeta mechanisms at all:
from functools import partial
def abstractclassproperty(func):
func._abstract_property = True
return func
class clsproperty(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.func(owner)
class ABCAbstractClsProperty(type):
def __new__(mcls, name, bases, namespace, **kw):
new_cls = super(ABCAbstractClsProperty, mcls).__new__(mcls, name, bases, namespace, **kw)
for attr_name in dir(new_cls): # Dir retrieves attributes from all superclasses
attr = getattr(new_cls, attr_name)
if getattr(attr, "im_func", None): # Python 2 specific normalization.
attr = attr.im_func
if getattr(attr, '_abstract_property', False) and new_cls.__dict__.get(attr_name) is not attr:
raise TypeError("Can't create class {!r}: abstract property {!r} not implemented".format(name, attr_name))
return new_cls
""" # Python 3:
class A(metaclass=ABCAbstractClsProperty):
#abstractclassproperty
def cl(cls):
pass
"""
class A(object):
__metaclass__ = ABCAbstractClsProperty
#abstractclassproperty
def cl(cls):
pass
try:
class B(A):
pass
except TypeError:
print("Check ok")
class C(A):
#clsproperty
def cl(cls):
return "ho ho ho " + cls.__name__
print(C.cl)

Do django class based views inherit method_decorators?

I'm using django class-based views. Suppose there is a ListView like this:
#method_decorator(ensure_csrf_cookie, name='dispatch')
class SomeView(ListView):
...
If another class-based view inherits SomeView, Does it inherit the "ensure_csrf_cookie" too? Or it has to be defined on every subclasses explicitly?
The "#decorator" syntax is just syntactic sugar that transforms this:
#decorator
class SomeClass(parent):
pass
into this:
class SomeClass(parent):
pass
SomeClass = decorator(SomeClass)
IOW, whatever decorator do is done after the class is created, so as a general rule, you cannot count on it being inherited by child classes of SomeClass - whether "what the decorator did" will actually be inherited (or not) really depends on both "what the decorator did" AND the child class definition.
wrt/ your concrete use case: method_decorator is used to decorate a given method of your class (the dispatch method in your example). If your child class doesn't override this method, then it will be looked up on the parent class. In this case, you will indeed end up using the decorated method. But if you override the decorated method in your subclass, the new method will be used instead of the parent's one, so it will not be automagically decorated and you'll have to apply the decorator again.
FWIW, it's quite easy to test by yourself:
>>> def decorator(func):
... def wrapper(*args, **kw):
... print("before %s(%s, %s)" % (func, args, kw)
... )
... return func(*args, **kw)
... return wrapper
...
>>> from django.utils.decorators import method_decorator
>>> #method_decorator(decorator, name='foo')
... class Bar(object):
... def foo(self):
... print("%s.foo()" % self)
...
>>> b = Bar()
>>> b.foo()
before <function bound_func at 0x7fefab044050>((), {})
<Bar object at 0x7fefab09af10>.foo()
>>> class Quux(Bar): pass
...
>>> q = Quux()
>>> q.foo()
before <function bound_func at 0x7fefab044050>((), {})
<Quux object at 0x7fefab041110>.foo()
>>> class Baaz(Bar):
... def foo(self):
... print("this is Baaz.foo")
...
>>> bz = Baaz()
>>> bz.foo()
this is Baaz.foo
>>>
It has to be defined on every subclasses explicitly. Because method_decorator is just function and do some calculations(it is dependent on how you write you decorator) then it will call your class SomeView. If you inherit the SomeView then you have to use the method_decorator explicitly for that new class. It might help.

Is it possible to access a variable in another method within the same class?

I'd like to know if it is possible for access the variable defined in function1 into function2 within the same MainWindow class as in the following code? How about accessing a variable in another method but from a different class?
import os
class MainWindow():
def __init__(self, name):
self.name = name
def function1(self):
if self.work != []:
self.variable = self.existing_work.variable
def function2(self):
if not os.path.isdir(self.variable):
return False
else:
return True
Any attribute you create, as in self.variable, is accessible from any other method in the same way that self.name is provided that you create it before attempting to access it.
In your example, function1 must run before function2 else it will fail.

How do I find the class of my static method inside of it?

Given I am inside a #staticmethod, how can I find the name of the current class ?
As i don't have access to self.__class__.__name__
As seen in this answer How to get (sub)class name from a static method in Python?
you can change the #staticmethod to a #classmethod which takes the class as a parameter:
class Bar(object):
#classmethod
def bar(cls):
print cls.__name__
....
If you have control of the method (e.g. it's one you wrote), the best way is to use the #classmethod decorator instead. That will send the class as the first argument:
class Spam(object):
#classmethod
def eggs(cls):
return cls.__name__

Mixin question for ModelAdmin

I'm overriding a ModelAdmin method thus:
def response_change(self, request, obj):
# alter redirect location if 'source' is found in GET
response = super(JobOptions, self).response_change(request, obj)
source = request.GET.get('source', None)
if source:
response['location'] = source
return response
Rather than repeat this on every model I'd like to make it a mixin.
If I do:
def RedirectMixin(admin.ModelAdmin)
and then:
def MyModel(admin.ModelAdmin, RedirectMixin)
then I get a MRO error.
However if RedirectMixin doesn't inherit from admin.ModelAdmin then the method doesn't get called.
An additional problem is how to generalise the super() call so it doesn't have the superclass hard-coded in.
Firstly, I presume you mean class rather than def in your examples.
Anyway, the right way to use a Mixin is to use it first in the list of classes to inherit. So:
class RedirectMixin(object):
and
class MyModelAdmin(RedirectMixin, admin.ModelAdmin):
This is because Python looks through all parent classes in order of declaration to find the method, and calls the first one it finds.
As for super, this shouldn't be mentioning the superclass at all - that's the whole point of it. It should reference the current class:
return super(MyModelAdmin, self).__init__(self, *args, **kwargs)
or whatever.
Edit after comments Yes, the mixin should refer to its own class in the super call. Consider the following:
In [1]: class BaseClass(object):
...: def my_function(self):
...: print 'base my_function'
...:
In [2]: class Mixin(object):
...: def my_function(self):
...: print 'mixin my_function'
...: super(Mixin, self).my_function()
...:
In [3]: class MyDerivedClass(Mixin, BaseClass):
...: pass
...:
Now if you instantiate the subclass and call its my_function method, the MRO will happen as you expect, even though Mixin doesn't inherit from BaseClass:
In [4]: m=MyDerivedClass()
In [5]: m.my_function()
mixin my_function
base my_function
The error you mention comes if you fail to make Mixin a descendant of object - if you don't, it's an old-style class, which doesn't support the use of super.