setting class attributes in class call - python

I am just wondering if there is a shortcut to setting default attributes.
I generally would do
class class1(object):
def __init__(self, att1='X'):
self.att1 = att1
Is there a shortcut in the lines off
class class1(object):
def __init__(self, self.att1='X'):
I assume at the moment of the call, the object does not exist, so seem logical that this way does not work, but maybe there is sort of less verbose way to deal with this when there is a lot more attributes to be set.
Any ideas?

Try something like:
class class1(object):
att1='X'
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

Related

Python mixins and types, dependencies

I work on a project with a huge class. Initially they were implemented as functions that just get imported, like in this answer:
def plot(self, x, y):
print(self.field)
def clear(self):
# body
#classmethod
def from_file(cls, path):
# body
class Fitter(object):
def __init__(self, whatever):
self.field = whatever
# Imported methods
from .some_file import plot, clear, from_file
...
But I think it's not the best solution, IDE is mad on the code because it cannot find field in the external methods and considers classmethod on some functions as an error. I hope mixins can help with it.
But I see the similar problem in this approach: mixin classes don't have a base class with all the common methods and fields specified (an example in Django), so IDE and linters cannot find definitions and understand the code correctly too... I tried to use some common base class, as the following:
class FitterBase(object):
def __init__(self, whatever):
self.field = whatever
class FiterMixin(FitterBase):
def plot(self, x, y):
print(self.field)
def clear(self):
# body
#classmethod
def from_file(cls, path):
# body
class Fitter(FitterBase, FiterMixin):
pass
But the interpreter raises an error:
TypeError: Cannot create a consistent method resolution
Is there any solution to this problem? It's really important because the class contains dozens of big methods, and correct inheritance would help a lot.
Python is trying to construct an MRO for Fitter in which FitterBase both precedes and follows FitterMixin; the former because FitterBase is listed first in the seance of base classes, the latter because it is the parent of FitterMixin.
To resolve that issue, simply swap the order of the two base classes:
class Fitter(FitterMixin, FitterBase):
pass
There's no reason to list both, though, because FitterMixin already inherits from FitterBase:
class Fitter(FitterMixin):
pass
As this makes more obvious, FitterMixin isn't really a mix-in class, because you aren't mixing it with anything. Or, don't make FitterMixin subclass FitterBase:
class FitterBase:
def __init__(self, whatever):
self.field = whatever
class FitterMixin:
def plot(self, x, y):
print(self.field)
def clear(self):
pass
#classmethod
def from_file(cls, path):
pass
class Fitter(FitterBase, FitterMixin):
pass

Python: Make Class Itself Callable

My question might seem stupid. But, I wish to know if there is a way in Python to make a Class itself callable. No I'm not talking about making a Class Instance callable. I'm talking about something like this:
class Foo:
def __call__(value):
return do_something_with(value)
#note I didn't use self because I want the class itself to be callable, not an instance of it
a = Foo(some_random_value)
But this doesn't seem to work. So, is there any way to do it or is it impossible to do in Python?
As explained above, and for probably all use cases, this is a very bad idea, don't do it! (puppies will die!)
class Foo:
def __new__(self, value):
return Foo.__call__(value)
#classmethod
def __call__(cls, value):
return f'processed {value}'
print(Foo(42))
output:
processed 42

Declaring inner class out of the class

I want to use inner class in my code but I have problem with planning how should it looks like, maybe even it's bad use of it so you could help me to find other way to write it.
I wish this inner class would have been created in some if structure, depending on the string provided in input. It would be nice if I could write the code of this inner class outside it's parent class because it might be huge in the future and it should be easy to extend.
I was wondering if I should just use inheritage like Case1(Case1), but im not sure about this.
class Example:
def declare_specific_case(self):
if "case1" in foo:
class Case1:
pass
elif "case2" in foo:
class Case2:
pass
class Case1:
<some code which can be used in inner class>
So I expect that I can declare the code outside the class maybe even in other module.
You can do something like this:
class Class1: pass
class Class2: pass
class Wrapper:
def __init__(self, x):
if x:
self._inner = Class1
else:
self._inner = Class2
even you can add a convenience method just like:
class Wrapper:
# ...
def get_inner_class_instance(self, *args, **kwargs):
return self._inner(*args, **kwargs)
On the other hand, perhaps you want to look on how to implement the Factory Pattern using python. Take a look to this article: https://hub.packtpub.com/python-design-patterns-depth-factory-pattern/

How can I simply pass arguments to parent constructor in child class?

I want to design some derived classes in Python but don't know how to make it very simple without too much effort and code.
Let me explain, I have the following class:
class Page(object):
def __init__(self, name):
self.name = name
I want to derive some children:
class PageWithImage(Page):
def __init__(self, name, image):
# Need I do this boring code? - how to replace it?
super(PageWithImage, self).__init__(name = name)
self.image = image
How can I skip rewriting the whole list of variables for the call to the super method like name = name? (since there can be a lot of such variables)
How can I make it more readable? (less code is often more readable)
I do not like the code I wrote - since auto-completion doesn't work with this code:
class PageWithImage(Page):
def __init__(self, *args, **kwrds):
# Need I do this boring code? - how to replace it?
super(PageWithImage, self).__init__(*args, **kwrds)
self.image = image
I think that your code is quite broken or untested (bad indentation, bad syntax), because it won't run currently, maybe you should edit.
But if you want to simplify your "super call" :
class PageWithImage(Page):
def __init__(self, *args, **kwargs):
super(PageWithImage, self).__init__(*args, **kwargs)
It will takes all arguments and keywords arguments (remove the **kwargs if you don't need keywords arguments).
Yes, less code is often more readable, but it's not always the case, list comprehensions, complicated functions using *args and **kwargs, lambda, etc... can be obscure sometimes for a developer even if they save +20 characters.
So, if the number of parameters can be easily ~10, you should try to re-design or stuff them into a dictionnary, or a list, depending on the nature of these parameters.
There's no way to extend an argument list at the end in a easy way. If you want to do that, you pretty much need to write out all the arguments each time.
You can however extend the arguments at the start:
class Base(object):
def __init__(self, base_arg0, base_arg1, base_arg2):
pass
class Derived(Base):
def __init__(self, derived_arg, *args):
super().__init__(*args)
You'd call this with something like Derived(da, ba0, ba1, ba2) (note that the derived arg comes before the base args).
In Python 3, you can also specify keyword-only arguments, by putting a bare * in the argument list:
class BaseKW(object):
def __init__(self, *, base_arg):
pass
class DerivedKW(BaseKW):
def __init__(self, *, derived_arg, **kwargs):
super().__init__(**kwargs)
You could call this with either DerivedKW(derived_arg=da, base_arg=ba) or DerivedKW(base_arg=ba, derived_arg=da) (the order of the keyword arguments in the call does not matter).

Pythonic way to assign an instance of a subclass to a variable when a specific string is presented to the constructor of the parent class

I want to be able to create an instance of a parent class X, with a string "Q" as an extra argument.
This string is to be a name being an identifier for a subclass Q of the parent class X.
I want the instance of the parent class to become (or be replaced with) an instance of the subclass.
I am aware that this is probably a classic problem (error?). After some searching I haven't found a suitable solution though.
I came up with the following solution myself;
I added a dictionary of possible identifiers as keys for their baseclass-instances to the init-method of the parent class.
Then assigned the class-attribute of the corresponding subclass to the current instances class-attribute.
I required the argument of the init-method not to be the default value to prevent infinite looping.
Following is an example of what the code looks like in practice;
class SpecialRule:
""""""
name="Special Rule"
description="This is a Special Rule."
def __init__(self, name=None):
""""""
print "SpecialInit"
if name!=None:
SPECIAL_RULES={
"Fly" : FlyRule(),
"Skirmish" : SkirmishRule()
} #dictionary coupling names to SpecialRuleclasses
self.__class__= SPECIAL_RULES[name].__class__
def __str__(self):
""""""
return self.name
class FlyRule(SpecialRule):
""""""
name="Fly"
description="Flies."
def __init__(self):
""""""
print "FlyInit"+self.name
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
class SkirmishRule(SpecialRule):
""""""
name="Skirmish"
description="Skirmishes."
def __init__(self):
""""""
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
test=SpecialRule("Fly")
print "evaluating resulting class"
print test.description
print test.__class__
</pre></code>
output:
>
SpecialInit
FlyInitFly
SpecialInit
evaluating resulting class
Flies.
main.FlyRule
>
Is there a more pythonic solution and are there foresee-able problems with mine?
(And am I mistaken that its a good programming practice to explicitly call the .__init__(self) of the parent class in .__init__ of the subclass?).
My solution feels a bit ... wrong ...
Quick recap so far;
Thanks for the quick answers
# Mark Tolonen's solution
I've been looking into the __new__-method, but when I try to make A, B and C in Mark Tolonen's example subclasses of Z, I get the error that class Z isn't defined yet. Also I'm not sure if instantiating class A the normal way ( with variable=A() outside of Z's scope ) is possible, unless you already have an instance of a subclass made and call the class as an attribute of an instance of a subclass of Z ... which doesn't seem very straightforward. __new__ is quite interesting so I'll fool around with it a bit more, your example is easier to grasp than what I got from the pythondocs.
# Greg Hewgill's solution
I tried the staticmethod-solution and it seems to work fine. I looked into using a seperate function as a factory before but I guessed it would get hard to manage a large program with a list of loose strands of constructor code in the main block, so I'm very happy to integrate it in the class.
I did experiment a bit seeing if I could turn the create-method into a decorated .__call__() but it got quite messy so I'll leave it at that.
I would solve this by using a function that encapsulates the choice of object:
class SpecialRule:
""""""
name="Special Rule"
description="This is a Special Rule."
#staticmethod
def create(name=None):
""""""
print "SpecialCreate"
if name!=None:
SPECIAL_RULES={
"Fly" : FlyRule,
"Skirmish" : SkirmishRule
} #dictionary coupling names to SpecialRuleclasses
return SPECIAL_RULES[name]()
else:
return SpecialRule()
I have used the #staticmethod decorator to allow you to call the create() method without already having an instance of the object. You would call this like:
SpecialRule.create("Fly")
Look up the __new__ method. It is the correct way to override how a class is created vs. initialized.
Here's a quick hack:
class Z(object):
class A(object):
def name(self):
return "I'm A!"
class B(object):
def name(self):
return "I'm B!"
class C(object):
def name(self):
return "I'm C!"
D = {'A':A,'B':B,'C':C}
def __new__(cls,t):
return cls.D[t]()

Categories

Resources