not sure about the proper wording for that, but essentially what I would like to ask is if it is possible in python do something like this:
class Customer:
self.name = 'Freddy'
#reportMarketing
self.surname = 'Krueger'
self.eyes = 'Blue'
#reportMarketing
self.address = 'Elm Street'
#reportAccounting
self.tax_id = '8ab9a66cf'
...
where #reportMarketing and #reportAccounting would be decorators (of sorts). The idea is that an instance like the one above could be then passed to some 'reporting class' that - based on whether the instance's attribute is decorated with #reportMarketing or a #reportAccounting, would then consider it for a specific 'reporting'. For instance, imagine you have customers database with instances like the one above, and you want data/attributes decorated with reportMarketing to be included in a report that goes to your marketing department, while the data/attributes decorated with reportAccounting to be included in a report that goes to your accounting department.
I guess conceptually, my question is can I even have decorators for attributes? I understand they are 'typically' (always?) meant for functions.
Also, to give more background, the classes I deal with have plenty of attributes (each), so going through all of them manually is quite error-prone, and so I thought dealing with it by simply decorating the couple of ones I'm after, is the cleanest and most extensible in the future.
Related
I have a class called House()
To make a new instance of House I can pass data like
house = House(roof = roof)
To standardize how Houses get created (and make use of type annotations) House has a .new() static method that looks like:
class House():
#staticmethod
def new(roof: Roof):
house = House(roof = roof)
# do other stuff for new method, ie may add to session, etc.
return house
However, this is kind of annoying because if house has say 10 attributes, it means there's a lot of copy and paste. For example here, to use keyword args (which is preferred), 'roof' is repeated 3 times.
Docs states that __init__ is not called when recreating, but I feel a bit strange over riding it for a .new() method or is this correct?
Also I feel like __init__ doesn't really solve the generic concern. I'm looking for the best of both worlds, where the existing defined properties are available on init, but I can also define logic that's different for each class.
Thinking along the lines of attributes from kwargs maybe but not exactly it?
An assumption is that there will always be some attributes that are not needed. Part of this is enforcing that say a house always needs a roof, but an attribute like owner doesn't need to be populated when it's first created. But if a new developer joins the team and calls House.new() they should be able to see that definition of what attributes are needed.
For example I can pass roof = Column(..., default = 1)
is there a way in Column or similar to say something like required?
I am designing an RPG and would like to have the ability to attach classes to each other. What I'm looking to do is have say an Item class. The weapon class would inherit from it. A sword would be an instance of the weapon class. I want to then be able to attach properties to the sword. These properties would be other classes. For example I could attach the container class to it and the sword (only that instance of the sword) would become a container. I could also maybe attach something like an enchantment to that sword.
For a bonus it would be nice to be able to combine instances as well. So instead of having to have a fire_enchantment class I could just make it an instance of Enchantment and attach it to the sword instance.
I've googled around and haven't been able to find a design pattern that fits this. I recall studying one but can't remember what it was called (Was a few years ago)
I'm at a loss of of which design pattern allowed this. The combining of multiple classes dynamically.
I think you seem to understand the idea of inheritance in python (e.g. class Subclass(Superclass): ) so I won't cover that here.
The classes you want to 'attach' can be treated as any other variable within the Weapon class.
class Enchantment(object):
def __init__(self, name, type):
self.name = name
self.type = type
# can define more member variables here, and set with setter methods
# more Enchantment methods here...
class Weapon(object):
def __init__(self, name, type)
self.name = name
self.type = type
self.enchantments = []
# more Weapon member variables here
def add_enchantment(self, enchantment):
# any logic you need to check when adding an enchantment
self.enchantments.append(enchantment)
Then in wherever your game code is running you could do
sword = Weapon('My sword', 'sword')
fire_enchantment = Enchantment('Fireball', 'fire')
sword.add_enchantment(fire_enchantment)
You can then add methods on the Weapon class to do things with the enchantments/add certain logic.
The enchantment is still an instance of an object, so if you access it in the list (maybe by identifying it by its name, or looping through the list) all its methods and variables are accessible. You just need to build an interface to it via the Weapon class e.g. get_enchantment(self, name), or have other methods in the Weapon class interact with it (e.g. when you attack you might loop through the enchantments and see if they add any extra damage).
There's obviously design considerations about how you design your classes (the above was thrown together for example and doesn't include inheritance). For example you might only allow one enchantment per weapon, in which case you shouldn't use a list in the weapon object, but could just set self.enchantment = None in the constructor, and set self.enchantment = enchantment in the add_enchantment method.
The point I'm making is you can treat instances of Enchantment or other 'attachable' classes as variables. Just make sure you create an instance of the class e.g. fire_enchantment = Enchantment('Fireball', 'fire').
There's plenty of reading out there in terms of inheritance and OOP in general. Hope this helps!
Additional answer from OP
I think the Mixin pattern is what I was looking for. After digging around more I found this post which has an answer for dynamic mixin's.
I am writing some code that is an upside down triangle of inheritance. I have a base Linux class that has a CLIENT attr which holds a connection. I have several APIs that are logically separated (kvm, yum, gdb, dhcp, etc..) that use CLIENT but I only want the user to need to create a single instance of Linux class but be able to call all the methods from the Parent classes. While maintaining the nice logical code separation among the parents:
class Linux(
SSHClient,
yum.Yum,
kvm.Kvm,
ldap.Ldap,
lshw.Lshw,
packet_capture.Tcpdump,
tc.TrafficControl,
networking.Networking,
gdb.Gdb,
dhcp.Dhcp,
httputil.Http,
scp.Scp,
fileutils.FileUtils):
I made a little example:
class Dad(object):
def __init__(self):
raise NotImplementedError("Create Baby instead")
def dadCallBaby(self):
print('sup {}'.format(self.babyName))
class Mom(object):
def __init__(self):
raise NotImplementedError("Create Baby instead")
def momCallBaby(self):
print('goochi goo {}'.format(self.babyName))
class Baby(Mom, Dad):
def __init__(self, name):
self.babyName = name
def greeting(self):
self.momCallBaby()
self.dadCallBaby()
x=Baby('Joe')
x.greeting()
What is doing this called? Is this Duck Typing? And is there a better option?
There's really no such thing as "child-only attributes".
The attribute babyName is just stored in each object's namespace, and looked up there. Python doesn't care that it happened to be stored by Baby.__init__. And in fact, you can write store the same attribute on a Mom that isn't a Baby and it will work the same way:
class NotABaby(Mom):
def __init__(self): pass
mom = NotABaby()
mom.babyName = 'Me?'
mom.momCallBaby()
Also, it's hard to suggest a better way to do what you're doing, because what you're doing is inherently confusing and probably shouldn't be done.
Inheritance normally means subtyping—that is, Baby should only be a subclass of Mom if every Baby instance is usable as a Mom.1
But a baby is not a mom and a dad.2 A baby has a mom and a dad. And the way to represent that is by giving Baby attributes for its mom and dad:
class Baby(object):
def __init__(self, mom, dad, name):
self.mom, self.dad, self.name = mom, dad, name
def greeting(self):
self.mom.momCallBaby(self.name)
self.dad.dadCallBaby(self.name)
Notice that, e.g., this means that the same woman can be the mom of two babies. Since that's also true of the real-life thing you're modeling here, that's a sign that you're modeling things correctly.
Your "real" example is a little less clear, but I suspect the same thing is going on there.
The only reason you want to use inheritance, as far as I can tell, is:
I only want the user to need to create a single instance of Linux class
You don't need, or want, inheritance for that:
class Linux(object):
def __init__(self):
self.ssh_client = SSHClient()
self.yum = yum.Yum()
# etc.
… but be able to call all the methods from the Parent classes
If yum.Yum, ldap.Ldap and dhcp.Dhcp both have methods named lookup, which one would be called by Linux.lookup?
What you probably want is to just leave the attributes as public attributes, and use them explicitly:
system = Linux()
print(system.yum.lookup(package))
print(system.ldap.lookup(name))
print(system.dhcp.lookup(reservation))
Or you'll want to provide a "Linux API" that wraps all the underlying APIs:
def lookup_package(self, package):
return self.yum.lookup(package)
def lookup_ldap_name(self, name):
return self.ldap.lookup(name)
def lookup_reservation(self, reservation):
return self.dhcp.lookup(reservation)
If you really do want to just forward every method of all of your different components, and you're sure that none of them conflict with each other, and there are way too many to write out manually, you can always do it programmatically, by iterating all of the classes, iterating inspect.getmembers of each one, filtering out the ones that start with _ or aren't unbound methods, creating a proxy function, and setattr-ing it onto Linux.
Or, alternatively (probably not as good an idea in this case, but very commonly useful in cases that aren't that different), you can proxy dynamically, at method lookup time, by implementing a __getattr__ method (and, often, a __dir__ method).
I think one of these two kinds of proxying may be what you're really after here.
1. There are some cases where you want to inherit for reasons other than subtyping. For example, you inherit a mixin class to get implementations for a bunch of methods. The question of whether your class is usable wherever that mixin's instances are usable doesn't really make sense, because the mixin isn't usable anywhere (except as a base class). But the subtyping is still the standard that you're bending there.
2. If it is, call Child Protective Services. And also call Professor X, because that shouldn't be physically possible.
When and how are static methods suppose to be used in python? We have already established using a class method as factory method to create an instance of an object should be avoided when possible. In other words, it is not best practice to use class methods as an alternate constructor (See Factory method for python object - best practice).
Lets say I have a class used to represent some entity data in a database. Imagine the data is a dict object containing field names and field values and one of the fields is an ID number that makes the data unique.
class Entity(object):
def __init__(self, data, db_connection):
self._data = data
self._db_connection
Here my __init__ method takes the entity data dict object. Lets say I only have an ID number and I want to create an Entity instance. First I will need to find the rest of the data, then create an instance of my Entity object. From my previous question, we established that using a class method as a factory method should probably be avoided when possible.
class Entity(object):
#classmethod
def from_id(cls, id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return cls(data, db_connection)
def __init__(self, data, db_connection):
self._data = data
self._db_connection
# Create entity
entity = Entity.from_id(id_number, db_connection)
Above is an example of what not to do or at least what not to do if there is an alternative. Now I am wondering if editing my class method so that it is more of a utility method and less of a factory method is a valid solution. In other words, does the following example comply with the best practice for using static methods.
class Entity(object):
#staticmethod
def data_from_id(id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return data
# Create entity
data = Entity.data_from_id(id_number, db_connection)
entity = Entity(data)
Or does it make more sense to use a standalone function to find the entity data from an ID number.
def find_data_from_id(id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return data
# Create entity.
data = find_data_from_id(id_number, db_connection)
entity = Entity(data, db_connection)
Note: I do not want to change my __init__ method. Previously people have suggested making my __init__ method to look something like this __init__(self, data=None, id_number=None) but there could be 101 different ways to find the entity data so I would prefer to keep that logic separate to some extent. Make sense?
When and how are static methods suppose to be used in python?
The glib answer is: Not very often.
The even glibber but not quite as useless answer is: When they make your code more readable.
First, let's take a detour to the docs:
Static methods in Python are similar to those found in Java or C++. Also see classmethod() for a variant that is useful for creating alternate class constructors.
So, when you need a static method in C++, you need a static method in Python, right?
Well, no.
In Java, there are no functions, just methods, so you end up creating pseudo-classes that are just bundles of static methods. The way to do the same thing in Python is to just use free functions.
That's pretty obvious. However, it's good Java style to look as hard as possible for an appropriate class to wedge a function into, so you can avoid writing those pseudo-classes, while doing the same thing is bad Python style—again, use free functions—and this is much less obvious.
C++ doesn't have the same limitation as Java, but many C++ styles are pretty similar anyway. (On the other hand, if you're a "Modern C++" programmer who's internalized the "free functions are part of a class's interface" idiom, your instincts for "where are static methods useful" are probably pretty decent for Python.)
But if you're coming at this from first principles, rather than from another language, there's a simpler way to look at things:
A #staticmethod is basically just a global function. If you have a function foo_module.bar() that would be more readable for some reason if it were spelled as foo_module.BazClass.bar(), make it a #staticmethod. If not, don't. That's really all there is to it. The only problem is building up your instincts for what's more readable to an idiomatic Python programmer.
And of course use a #classmethod when you need access to the class, but not the instance—alternate constructors are the paradigm case for that, as the docs imply. Although you often can simulate a #classmethod with a #staticmethod just by explicitly referencing the class (especially when you don't have much subclassing), you shouldn't.
Finally, getting to your specific question:
If the only reason clients ever need to look up data by ID is to construct an Entity, that sounds like an implementation detail you shouldn't be exposing, and it also makes client code more complex. Just use a constructor. If you don't want to modify your __init__ (and you're right that there are good reasons you might not want to), use a #classmethod as an alternate constructor: Entity.from_id(id_number, db_connection).
On the other hand, if that lookup is something that's inherently useful to clients in other cases that have nothing to do with Entity construction, it seems like this has nothing to do with the Entity class (or at least no more than anything else in the same module). So, just make it a free function.
The answer to the linked question specifically says this:
A #classmethod is the idiomatic way to do an "alternate constructor"—there are examples all over the stdlib—itertools.chain.from_iterable, datetime.datetime.fromordinal, etc.
So I don't know how you got the idea that using a classmethod is inherently bad. I actually like the idea of using a classmethod in your specific situation, as it makes following the code and using the api easy.
The alternative would be to use default constructor arguments like so:
class Entity(object):
def __init__(self, id, db_connection, data=None):
self.id = id
self.db_connection = db_connection
if data is None:
self.data = self.from_id(id, db_connection)
else:
self.data = data
def from_id(cls, id_number, db_connection):
filters = [['id', 'is', id_number]]
return db_connection.find(filters)
I prefer the classmethod version that you wrote originally however. Especially since data is fairly ambiguous.
Your first example makes the most sense to me: Entity.from_id is pretty succinct and clear.
It avoids the use of data in the next two examples, which does not describe what's being returned; the data is used to construct an Entity. If you wanted to be specific about the data being used to construct the Entity, then you could name your method something like Entity.with_data_for_id or the equivalent function entity_with_data_for_id.
Using a verb such as find can also be pretty confusing, as it doesn't give any indication of the return value — what is the function supposed to do when it's found the data? (Yes, I realize str has a find method; wouldn't it be better named index_of? But then there's also index...) It reminds me of the classic:
I always try to think what a name would indicate to someone with (a) no knowledge of the system, and (b) knowledge of other parts of the system — not to say I'm always successful!
Here is a decent use case for #staticmethod.
I have been working on a game as a side project. Part of that game includes rolling dice based on stats, and the possibility of picking up items and effects that impact your character's stats (for better or worse).
When I roll the dice in my game, I need to basically say... take the base character stats and then add any inventory and effect stats into this grand netted figure.
You can't take these abstract objects and add them without instructing the program how. I'm not doing anything at the class level or instance level either. I didn't want to define the function in some global module. The last best option was to go with a static method for adding up stats together. It just makes the most sense this way.
class Stats:
attribs = ['strength', 'speed', 'intellect', 'tenacity']
def __init__(self,
strength=0,
speed=0,
intellect=0,
tenacity=0
):
self.strength = int(strength)
self.speed = int(speed)
self.intellect = int(intellect)
self.tenacity = int(tenacity)
# combine adds stats objects together and returns a single stats object
#staticmethod
def combine(*args: 'Stats'):
assert all(isinstance(arg, Stats) for arg in args)
return_stats = Stats()
for stat in Stats.attribs:
for _ in args:
setattr(return_stats, stat,
getattr(return_stats, stat) + getattr(_, stat))
return (return_stats)
Which would make the stat combination calls work like this
a = Stats(strength=3, intellect=3)
b = Stats(strength=1, intellect=-1)
c = Stats(tenacity=5)
print(Stats.combine(a, b, c).__dict__)
{'strength': 4, 'speed': 0, 'intellect': 2, 'tenacity': 5}
I'm getting back to programming for Google App Engine and I've found, in old, unused code, instances in which I wrote constructors for models. It seems like a good idea, but there's no mention of it online and I can't test to see if it works. Here's a contrived example, with no error-checking, etc.:
class Dog(db.Model):
name = db.StringProperty(required=True)
breeds = db.StringListProperty()
age = db.IntegerProperty(default=0)
def __init__(self, name, breed_list, **kwargs):
db.Model.__init__(**kwargs)
self.name = name
self.breeds = breed_list.split()
rufus = Dog('Rufus', 'spaniel terrier labrador')
rufus.put()
The **kwargs are passed on to the Model constructor in case the model is constructed with a specified parent or key_name, or in case other properties (like age) are specified. This constructor differs from the default in that it requires that a name and breed_list be specified (although it can't ensure that they're strings), and it parses breed_list in a way that the default constructor could not.
Is this a legitimate form of instantiation, or should I just use functions or static/class methods? And if it works, why aren't custom constructors used more often?
In your example, why not use the default syntax instead of a custom constructor:
rufus = Dog( name='Rufus', breeds=['spaniel','terrier','labrador'] )
Your version makes it less clear semantically IMHO.
As for overriding Model constructors, Google recommends against it (see for example: http://groups.google.com/group/google-appengine/browse_thread/thread/9a651f6f58875bfe/111b975da1b4b4db?lnk=gst&q=python+constructors#111b975da1b4b4db) and that's why we don't see it in Google's code.
I think it's unfortunate because constructor overriding can be useful in some cases, like creating a temporary property.
One problem I know of is with Expando, anything you define in the constructor gets auto-serialized in the protocol buffer.
But for base Models I am not sure what are the risks, and I too would be happy to learn more.
There's usually no need to do something like that; the default constructor will assign name, and when working with a list it almost always makes more sense to pass an actual list instead of a space-separated string (just imagine the fun if you passed "cocker spaniel" instead of just "spaniel" there, for one thing...).
That said, if you really need to do computation when instantiating a Model subclass instance, there's probably nothing inherently wrong with it. I think most people probably prefer to get the data into the right form and then create the entity, which is why you're not seeing a lot of examples like that.