class overwrite __init__ default parameter - python

I import a class Foo that has a default parameter dir upon which if performs a function doit. How can I change the default dir? Do I need to inherit this class and then change it, how?
class Foo(object):
def __init__(self, dir='xxx'):
self.bar = doit(dir) # fails because xxx is wrong

why don't you just provide a different argument when you construct an instance of the class:
foo = Foo(dir='something else')
btw: dir is a python built-in and therefore not the best choice as variable name.
if you want the default changed, you can inherit indeed:
class MyFoo(Foo):
def __init__(self, d='somethig else'):
super().__init__(d=d)

Just create a factory function for Foo objects and be done with it:
def create_foo():
return Foo(dir='my correct value goes here')
Since you're importing Foo, you could go a step further and just shadow Foo like this:
def Foo():
import foo
return foo.Foo(dir='my correct value goes here')
Of course you can inherit from Foo. Be sure to look up how to call the base
class constructors. I find that sooo hard to memorize that I just end up google it. Every. Single. Time.
BTW: Looks like #hiro protagonist already has the calling super figured out.

Related

Overwrite method or derive?

For a given class, is it better/fancier/more in accordance with Python Zen to overwrite a method (I.e., assign another function to it) or derive from that class and overwrite it in the new class.
So this:
from foo import Bar
def mybaz(self):
pass
Bar.baz = mybaz
Or:
from foo import bar
class Mybar(Bar):
def baz(self):
pass
If it makes a difference, please refer to Python3
Follow up: is the answer different for magic methods?
Second way is more preferable as it doesn't change the base class, but extends it, take a look at the open/closed principle.

Python factory method with external function

I've read this SO discussion about factory methods, and have an alternate constructor use case.
My class looks like this:
class Foo(object):
def __init__(self, bar):
self.bar = bar
#classmethod
def from_data(cls, datafile):
bar = datafile.read_bar()
# Now I want to process bar in some way
bar = _process_bar(bar)
return cls(bar)
def _process_bar(self, bar)
return bar + 1
My question is, if a #classmethod factory method wants to use a function in its code, should that function (_proces_bar) be:
A #classmethod, which seems a bit weird because you won't ever call it like Foo._process_bar()
A method outside of the class Foo but in the same .py file. I'd go with this, but it seems kind of weird. Will those methods always be available to an instance of Foo, regardless of how it was instantiated? (e.g. what if it's saved to a Pickle then reloaded? Presumably methods outside the class will then not be available!)
A #staticmethod? (see 1. This seems weird)
Something else? (but not this!)
The "right solution" depends on your needs...
If the function (_process_bar) needs an access to class Foo (or the current subclass of...) then you want a classmethod - which should be then called as cls._process_bar(), not Foo._process_bar().
If the function doesn't need an access to the class itself but you still want to be able to override it in subclasses (IOW : you want class-based polymorphism), you want a staticmethod
Else you just want a plain function. Where this function's code lives is irrelevant, and your import problems are othogonal.
Also, you may (or not, depending on your concrete use case) want to allow for more flexiblity using a callback function (possibly with a default), ie:
def process_bar(bar):
return bar + 1
class Foo(object):
#classmethod
def from_data(self, datafile, processor=process_bar):
bar = datafile.read_bar()
bar = processor(bar)
return cls(bar)

Execute Method within Class Python

I'm trying to call a method within a class MyClass and have its value returned.
class MyClass:
def __init__(self):
print " Class Initialized"
def gather_path(self):
self.tld_object = Tld.objects.get(id=3,FKToClient=User.pk)
return self.tld_object
How do I return the value of self.tld_object by importing my class in Python intrepreter.
I'm importing like:
from MyApp.MyClass import gather_path()
I know, this is quite basic - I'm relatively new to OOP in Python.
how do I then call this method to return the value of return self.tld_object within gather_path() method?
It depends on what you're trying to do, but typically, I think the code importing your class would look like this:
from MyApp import MyClass
my_instance = MyClass()
value = my_instance.gather_path()
The value variable will now contain tld_object's value.
If you don't want to instantiate MyClass in order to call get_path(), you need to make get_path() either a class or static method.
From your example, it's not clear that you need to set self.tld_object, since you're just returning it from gather_path() anyway, unless other methods are relying on that state under the hood. If you are, though, it would be better practice to declare it in __init__, even if you set it to None. Alternatively, if all instances of MyClass are going to use the same value of tld_object, you could make it a class variable, and just declare it outside of any method, like so:
class MyClass:
tld_object = Tld.objects.get(id=3,FKToClient=User.pk)
def gather_path(self):
return self.tld_object
Not sure how much of that is relevant to your needs, it's a bit hard to tell from the given example. If I were writing this (given what you've said so far), I'd do the following:
class MyClass:
def __init__(self):
self.tld_object = Tld.objects.get(id=3,FKToClient=User.pk)
# Maybe raise an exception or something if self.tld_object doesn't get set right
# Example of how to access tld_object from another method
def print_tld_object(self):
print self.tld_object
If you need to reach tld_object from outside the class, you would do the following in the other module:
from MyApp import MyClass
my_instance = MyClass()
tld = my_instance.tld_object

How to change class implementation efficiently

I'd like to change the implementation depending on a constructor argument. Below is an example showing what I mean:
class Device(object):
def __init__(self, simulate):
self.simulate = simulate
def foo(self):
if simulate:
self._simulate_foo()
else:
self._do_foo()
def _do_foo(self):
# do foo
def _simulate_foo(self):
# simulate foo
Now every call to foo() invokes an if clause. To avoid that I could bind the correct method dynamically to foo.
class Device(object):
def __init__(self, simulate):
if simulate:
self.foo = self._simulate_foo
else:
self.foo = self._do_foo()
def _do_foo(self):
# do foo
def _simulate_foo(self):
# simulate foo
Are there any drawbacks why this should not be done or other drawbacks I'm not aware? Is this really faster?(I'm aware that inheritance is another option)
I'd like to suggest the Replace Conditional with Polymorphism refactoring instead, as it solves your problem in a more elegant way than both the current code and the suggested alternative:
class Device(object):
def foo(self):
# do foo
class SimulatedDevice(object):
def foo(self):
# simulate foo
What you are doing is perfectly fine, and you'll find the technique used in plenty of Python frameworks. However, you may want to use timeit to check if this is really faster.
When you access instance.foo, Python will first look for it in the class definition to make sure it's not a data descriptor (such as a property), then look it up in the instance namespace, but this is a very fast lookup since foo is not defined in the class (setting self.foo stores it in the instance __dict__ namespace).
The if statement is almost certainly slower than that double lookup, since the if statement itself needs to look up self.simulate in the same manner, but the difference will be negligible.

Is there a way apply a decorator to a Python method that needs informations about the class?

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

Categories

Resources