First - please accept my apologies if this is a duplicate - I have the feeling that I have seen some sort of similar discussion before, but I really cannot find it.
My question regards object composition in Python that should look like inheritance from within each minor of the composite classes. The use case is that multiple object instances share a common core of attributes and their values (and not only a common structure, which would be a classic inheritance case instead).
I could do this with a simple attribute, i.e. by simply having each Class having one attribute called "shared_attributes", which is in itself a class storing all the values:
class CoreClass(object):
def __init__(self):
self.attr = 'asdf'
class CompClass1(object):
def __init__(self, core):
self.core_attr = core
class CompClass2(object):
def __init__(self, core):
self.core_attr = core
But this requires me to access each shared attribute through the class.core_attr attribute, which I do not want (for several reasons, one of which is that this would require an extensive rewrite of large sections of code).
So, instead I would like to use a composite pattern relying on Python's built-in __getattr__ object method, as such:
class TestClass1(object):
def __init__(self):
self.attr1 = 1
def func_a(self):
return 'a'
class CompClassBase(object):
def __init__(self, test_class):
self.comp_obj = test_class
def __getattr__(self, item):
return getattr(self.comp_obj, item)
class CompClass1(CompClassBase):
def __init__(self, test_class):
CompClassBase.__init__(self, test_class)
self.attr2 = 13
def func_b(self):
return '1b'
class CompClass2(CompClassBase):
def __init__(self, test_class):
CompClassBase.__init__(self, test_class)
self.attr2 = 23
def func_b(self):
return '2b'
if __name__ == '__main__':
tc = TestClass1()
cc1 = CompClass1(test_class=tc)
cc2 = CompClass2(test_class=tc)
print cc1.attr1
print cc1.attr2
print cc1.func_a()
print cc1.func_b()
print cc2.attr1
print cc2.attr2
print cc2.func_a()
print cc2.func_b()
Which prints, as it should, the following:
1
13
a
1b
1
23
a
2b
This pattern fits my needs perfectly, but there is something about it that wants to make me be certain about it ...
EDIT: (to respond to some comments) It is essential that this pattern will share all attributes in the shared class (given the previous objects):
cc1.attr1 = 'this is a test'
cc2.attr1 # must now be 'this is a test' as well!
2nd EDIT: I have used this pattern now for several weeks, and it works beautifully. However, I'm still hoping for some discussion, since I want to include this pattern in my standard toolkit from now on :-)
So now my question to you is simple: Is this a good practice? Does this particular Python pattern have any disadvantages? Should I be aware of some dangers here?
Related
So I am trying to get my data structure set up for an automated generator I am writing for a roleplaying game and I am having trouble with some specific inheritance quirks. Here is an excerpt of the data structure.
class data():
def __init__(self):
self.races = Races()
class Races(data):
def __init__(self):
self.humans = Humans()
class Humans(Races):
def __init__(self):
self.Characteristics = {
'Brawn':2,
'Agility':2,
'Intellect':2,
'Cunning':2,
'Willpower':2,
'Presence':2
}
There is a lot more in the structure but this is just a bottom to top overview. I also know it is indented weirdly but that is strictly stack overflow.
Now I wish to have two behaviors from this object.
The ability to call any characteristic with
data.races.humans.Characteristic['brawn']
as the calling format.
And too also be able to iterate through subclasses with a generator like:
(subclass for subclass in data.races.__subclasses__())
obviously after I have instantiated the object.
Now I have tried changing the structure several times and I can get it so EITHER I can call it with dot notation, but it returns AttributeError: 'Races' object has no attribute '__subclasses__'
Or vice versa by completely separating it into a more traditional structure but then I cannot call in dot notation and this makes it very hard to keep everything organized and readable.
Can anyone suggest what I am doing wrong or a more Pythonic way to approach the problem?
Let's start in the middle. Presumably, a character of any race has the same attributes, just different values for those attributes.
class Race:
def __init__(self):
self.life = 100 # 100% healthy
class Humanoid(Race):
def __init__(self):
super().__init__()
self.legs = 2
class Insectoid(Race):
def __init__(self):
super().__init__()
self.legs = 8
class Human(Humanoid):
def __init__(self):
super().__init__()
self.brawn = 2
self.agility = 2
self.intellect = 2
self.cunning = 2,
self.willpower = 2
self.presence = 2
class Elf(Humanoid):
def __init__(self):
super.__init__()
self.brawn = 1
self.agility = 3
self.intellect = 3
self.cunning = 2
self.willpower = 3
self.presence = 1
Now, any particular character would be instantiated as the correct class:
some_elf_1 = Elf()
some_human_1 = Human()
some_human_2 = Human()
for character in [some_elf_1, some_human_1, some_human_2]:
print("Brawn: ", character.brawn)
In the preceding, it doesn't matter what the actual type of each character is; as long as you know that it is some subclass of Race (or an instance of Race itself), it will have a brawn attribute that you can access.
You data class doesn't really seem necessary without more detail.
So, While the answer given put me on the right track I realized what I needed and am just throwing in my lot for any poor souls.
Firstly - I realized what was wrong with my generator, I was calling on the initialized object instead of the class object. Objects do not have a subclasses attrib and I was mis-informed by most of the guides I read!
Secondly, I considered using a metaclass to get the iterating behavior I wanted from my objects can simply be achieved with a registry attribute that is a dict of all the initialized subclasses.
lass Races(data):
def __init__(self):
self.humans = Humans()
self.droids = Droids()
self.twileks = Twileks()
self.registry = {
'humans':self.humans,
'droids':self.droids,
'twileks':self.twileks
}
This allows me to iterate through certain values for different races after they have been initialized.
Thanks for all the great answers!
I currently have the following two ways:
class Venue:
store = Database.store()
ids = [vid for vid in store.find(Venue.id, Venue.type == "Y")]
def __init__(self):
self.a = 1
self.b = 2
OR
class Venue:
#classmethod
def set_venue_ids(cls):
store = Database.store()
cls.ids = [vid for vid in store.find(Venue.id, Venue.type == "Y")]
def __init__(self):
self.a = 1
self.b = 2
And before using/instantiating the class I would call:
Venue.set_venue_ids()
What would be the correct way of achieving this?
If it's the first way, what would I do if the instantiation of the attribute required more complex logic that could be done more simply through the use of a function?
Or is there an entirely different way to structure my code to accomplish what I'm trying to do?
From a purely technical POV, a class is an instance of its metaclass so the metaclass initializer is an obvious candidate for class attributes initialization (at least when you have anything a bit complex).
Now given the canonical lifetime of a class object (usually the whole process), I would definitly not use an attribute here - if anyone adds or removes venues from your database while your process is running, your ids attributes will get out of sync. Why don't you use a classmethod instead to make sure your data are always have up to date ?
Oh and yes, another way to construct your Venue.ids (or any other class attribute requiring non-trivial code) without having complex code at the class top-level polluthing the class namespace (did you noticed that in your first example store becomes a class attributes too, as well as vid if using Python 2.x ?) is to put the code in a plain function and call that function from within your class statement's body, ie:
def list_venue_ids():
store = Database.store()
# I assume `store.find()` returns some iterator (not a `list`)
# if it does return a list, you could just
# `return store.find(...)`.
return list(store.find(Venue.id, Venue.type == "Y"))
class Venue(object):
ids = list_venue_ids()
def __init__(self):
self.a = 1
self.b = 2
I am having a situation where I have to make sure I only have one object. I am thinking about implementing singleton like following:
class One_Of_a_Kind:
def __init__(self):
self.do_some_setup()
class One_Creator:
Only_One = None
def __new__(cls, *args, **kwargs):
if One_Creator.Only_One:
return One_Creator.Only_One
else:
One_Creator.Only_One = One_of_a_Kind()
return One_Creator.Only_One
Since I am reading a lot about singleton (pros and cons), I am little hesitant in implementing this code. I would like to know if it is okay and/or considered good practice to use in a situation where only one object of certain class in needed ( or mandatory).
Is there a better way of implementing the same thing?
A better way is the Borg design pattern. It's very simple to implement in python:
class Borg:
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
You don't actually have a single instance, but each instance shares the same state - which is the part that matters.
When and how to use a singleton is a pretty broad question and primarily opinion based. That being said, I would implement it like this:
class Singleton(object):
state = {}
def __init__(self):
self.__dict__ = Singleton.state
The idea is taken from here. This is sort of a pseudo-singleton, as two instance will not share the same id:
>>> s1 = Singleton()
>>> s2 = Singleton()
>>> s1 is s2
False
>>> s1.x = 42
>>> s2.x
42
class ThirdPartyA(object):
def __init__(self):
...
def ...():
...
-------------------
from xxx import ThirdPartyA
class ThirdPartyB(object):
def a(self):
...
#call to ThirdPartyA
....
def b(self):
...
#call to ThirdPartyA
...
def c(self):
...
#call to ThirdPartyA
...
-----------------------------------
from xxx import ThirdPartyA
class MyCodeA(ThirdPartyA):
def __init__(self):
# overriding code
When overriding the __init__ method of A class, how could I instruct B class that it should call MyCodeA instead of ThirdPartyA in all its methods?
The real code is here:
CLass Geoposition: ThirdPartyA
Class GeopositionField: ThirdPartyB
My override to class Geoposition so it returns max 5 decimal digits:
class AccuracyGeoposition(Geoposition):
def __init__(self, latitude, longitude):
if isinstance(latitude, float) or isinstance(latitude, int):
latitude = '{0:.5f}'.format(latitude)
if isinstance(longitude, float) or isinstance(longitude, int):
longitude = '{0:.5f}'.format(longitude)
self.latitude = Decimal(latitude)
self.longitude = Decimal(longitude)
From your updated code, I think what you're trying to do is change GeopositionField. to_python() so that it returns AccuracyGeoposition values instead of Geoposition values.
There's no way to do that directly; the code in GeopositionField explicitly says it wants to construct a Geoposition, so that's what happens.
The cleanest solution is to subclass GeopositionField as well, so you can wrap that method:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
If creating a Geoposition and then re-wrapping the values in an AccuracyGeoposition is insufficient (because accuracy has already been lost), you might be able to pre-process things before calling the super method as well/instead. For example, if the way it deals with list is not acceptable (I realize that's not true here, but it serves as a simple example), but everything else you can just let it do its thing and wrap the result, you could do this:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
if isinstance(value, list):
return AccuracyGeoposition(value[0], value[1])
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
If worst comes to worst, you may have to reimplement the entire method (maybe by copying, pasting, and modifying its code), but hopefully that will rarely come up.
There are hacky alternatives to this. For example, you could monkeypatch the module to globally replace the Geoposition class with your AccuracyGeoposition class But, while that may save some work up front, you're almost certain to be unhappy with it when you're debugging things later. Systems that are designed for aspect-oriented programming (which is basically controlled monkeypatching) are great, but trying to cram it into systems that were designed to resist it will give you headaches.
Assuming your real code works like your example—that is, every method of B creates a new A instance just to call a method on it and discard it—well, that's a very weird design, but if it makes sense for your use case, you can make it work.
The key here is that classes are first-class objects. Instead of hardcoding A, store the class you want as a member of the B instance, like this:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass().a()
Now, you just create a B instance with your subclass:
b = B(OverriddenA)
Your edited version does a different strange thing: instead of constructing a new A instance each time to call methods on it, you're calling class methods on A itself. Again, this is probably not what you want—but, if it is, you can do it:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass.a()
However, more likely you don't really want either of these. You want to take an A instance at construction time, store it, and use it repeatedly. Like this:
class B(object):
def __init__(self, ainstance):
self.ainstance = ainstance
def a(self):
self.ainstance.a()
b1 = B(A())
b2 = B(OverriddenA())
If this all seems abstract and hard to understand… well, that's because we're using meaningless names like A, B, and OverriddenA. If you tell us the actual types you're thinking about, or just plug those types in mechanically, it should make a lot more sense.
For example:
class Vehicle(object):
def move(self):
print('I am a vehicle, and I am moving')
class Operator(object):
def __init__(self, vehicle):
self.vehicle = vehicle
def move(self):
print('I am moving my vehicle')
self.vehicle.move()
class Car(object):
def move(self):
print('I am a car, and I am driving')
driver = Operator(Car())
driver.move()
Background
I'm trying to figure out Python's descriptors by reading Lutz's Learning Python's section on the topic in which he says: "Like properties, descriptors are designed to handle specific attributes... Unlike properties, descriptors have their own state..."
Throughout the chapter he shows examples in which the managed attribute is actually stashed on the containing/wrapping object, as in:
def __set__(self, instance, value):
instance._name = value.lower()
I understand these examples and they seem to be common in write ups on the topic. That said, their benefit over properties isn't obvious to me and they seem to fall short of the internal state promised in the above quote.
At the end of the chapter he shows an example that is closer to what I pictured after reading "have their own state", as in:
def __set__(self, instance, value):
self.name = value.lower()
The example runs but does not do what I'd expect it to do. As the example is a bit long I've put it on Pastebin and added a last line that shows the unexpected behavior (Bob's name is now Sue). Here's a shorter demo snippet:
class Wrapper(object):
class ExampleDescriptor(object):
def __get__(self, instance, owner):
print "get %s" % self.state
return self.state
def __set__(self, instance, value):
print "set %s" % value
self.state = value
ex = ExampleDescriptor()
w1 = Wrapper()
w1.ex = 1
print w1.ex
w2 = Wrapper()
print w2.ex
w2.ex = 2
print w1.ex
print w1.ex is w2.ex
The output of which is:
set 1
get 1
1
get 1
1
set 2
get 2
2
get 2
get 2
True
None of this execution comes as a surprise after looking at the code carefully. The validation logic in the descriptor is making a de facto singleton out of this attribute on the wrapper class; however, it's hard to imagine this shared state was Lutz's intention, or the intention in this widely linked tutorial on the topic.
Question
Is it possible to make a descriptor that has internal state that is unique to the wrapping object without stashing that state on the wrapping object instances (as in the first snippet)? Is it possible to modify the CardHolder class from the linked example such that Bob does not end up as Sue?
"Like properties, descriptors are designed to handle specific attributes... Unlike properties, descriptors have their own state..."
I am not sure what point Lutz is trying to make as properties are, in fact, descriptors themselves.
But, even though descriptors do have their own state, it's not widely useful as, as you have discovered, you only get one descriptor object per class attribute instead of one per instance. This is why the instance is passed in, so that instance-unique values can be saved/accessed.
To prove the point that it is one descriptor object per attribute, you can try this slightly modified code from one of your links:
class RevealAccess(object):
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print 'Retrieving', self.name
return self.val
def __set__(self, obj, val):
print 'Updating' , self.name
self.val = val
class MyClass(object):
x = RevealAccess(10, 'var "x"')
y = RevealAccess(5, 'var "y"')
m = MyClass()
m.x
m.x = 20
m.x
m.y
What you should see:
Retrieving var "x"
Updating var "x"
Retrieving var "x"
Retrieving var "y"
To answer your question: Yes. But it's a pain.
class Stored(object):
"""A data descriptor that stores instance values in itself.
"""
instances = dict()
def __init__(self, val):
self.instances[self, None] = val
def __get__(self, obj, objtype):
return self.instances[self, obj]
def __set__(self, obj, val):
self.instances[self, obj] = val
class MyClass(object):
x = Stored(3)
y = Stored(9)
print(MyClass.x)
print(MyClass.y)
m = MyClass()
m.x = 42
print(m.x)
m.y = 19
print(m.y)
print(m.x)
As you've stated already, a descriptor is a class-level instance so its state is shared between each instance of the class.
The descriptor could store an internal hash of instances it's wrapping. To avoid circular references it'd be smarter to have the key be the id of the instance. The only reason I'd see to do this is if the descriptor's purpose is to aggregate these properties from different instances.
As for the second part of your question, just do as you stated already and store the underlying state on the instance instead of the descriptor and then Bob will not be Sue.
(A complement to other answers)
To attach state to instances you do not control without disturbing them, simply use a weak container; weakref.WeakKeyDictionary is appropriate here. The garbage collector will make sure that the descriptor's extra state doesn't linger after the instances are collected, and that the descriptor doesn't cause the instances to live longer than they normally would.