Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am writing a custom container class. A constituent object is created independently of the container, and can be a member of no container or multiple containers. The container's public API should support three operations:
iteration over all objects
insertion of a new object
removal of an existing object
The container does some additional work, and its precise implementation may change.
How can I write the public API to this class so that it remains stable as I change the implementation?
If the container is list-like, efficient removal requires the knowledge of the object's index; knowing the object itself is no good (I don't want to search the whole container for the element).
If the container is set-like, there's nothing equivalent to the index, and I need the object itself.
If the container is like a singly linked list, I need some kind of a reference to the object preceding the object being removed.
If the container is like a doubly linked list, I need a reference to the object itself.
I am thinking to have the removal method take a single argument reference, which has no meaning or use outside of the removal method. The iteration would yield a pair of (object, reference).
Is there any problem with this design? Is there an example or design pattern I can look up?
Ideally, I would rather have the iteration yield a complex object that contains both the original object and the reference, and exhibits the interface of both. But I don't suppose this is doable?
Most container types have a direction that they work well with - from index to indexed, from current to next, etc. Some are bidirectional, but far from all.
Trying to find a value in a python list without using an index is pretty much going to be O(n). You either need to embrace the O(n), or use a different type.
One thing that comes to mind on this, is that if you need to delete something quickly from a lot of container types en masse, you could add an "ignore_this" attribute to your values. If you set it to true, then all your container types start ignoring it, or even removing it when seen.
Just encapsulate a list and a dict / a list and a set, ...
Roughly doubles your memory usage and operation times, but clever encapsulation often makes nearly all problem-relevant operations O(1).
It might be worth looking at collections.OrderedDict if you're using Python 2.7 and above: http://docs.python.org/library/collections.html#collections.OrderedDict
Here's what I'll do unless someone else helps by finding a better solution:
# to get __hash__ and __eq__ return id(self)
class Reference:
def __init__(self, item):
self.item = item
class RemovalAPI:
def add_removal_info(self, item, removal_info):
try:
references = item.__reference
except AttributeError:
references = item.__reference = {}
references[Reference(self)] = removal_info
def get_removal_info(self, item):
try:
references = item.__reference
self_reference = Reference(self)
return references[self_reference]
class Container(list, RemovalAPI):
def __iter__(self):
for i in range(len(self)):
item = self[i]
self.add_removal_info(item, i)
yield item
def remove(self, item):
removal_info = self.get_removal_info(item)
del self[removal_info]
def insert(self, item):
self.add_removal_info(item, len(self))
self.append(item)
# do whatever post-processing I need
# ...
If I then decide to change the implementation from list to some other data structure, the public interface can remain unchanged:
class Container(orderedset, RemovalAPI):
# inheriting __iter__, remove from parent
def insert(self, item):
self.add(item)
# do whatever post-processing I need
# ...
Or...
class Container(linkedlist, RemovalAPI):
def __iter__(self):
it = super().__iter__()
last_item = None
for item in it:
self.add_removal_info(item, last_item)
yield item
def remove(self, item):
removal_info = self.get_removal_info(item)
if removal_info is None:
self.remove_first()
else:
self.remove_after(removal_info)
def insert(self, item):
self.add_removal_info(item, None)
self.add_to_front(item)
# do whatever post-processing I need
# ...
Related
This question already has answers here:
Optional chaining for Python objects: foo?.bar?.baz
(10 answers)
Closed 9 days ago.
for now I use this:
print(theObject.nestedObjectOne.NestedObjectTwo.NestedObjectThree if theObject and theObject.NestedOBjectOne and theObject.NestedObjectOne.NestedObjectTwo else "n/a")
In order to support a case where NestedObjectOne is None.
Is there a more elegant way to do this? Yes, I know I can write a function to traverse the object and check attributes recursively. I'm asking if there's any construct in python that does this as elegantly as ES6 for instance:
console.log(theObj?.theFirstNested?.theSecondNested)
Whether code should fail or just return some default value is a matter of opinion or style. Where ES6 defaults to undefined, other languages might pick something like null - in Python you might expect None.
However, multiple choices are available, and for some types, a value of 0 might make sense and None could cause havoc, so Python chooses to cause your code to fail when it accesses non-existent attributes.
There's a few ways to deal with it gracefully though.
try .. except:
try:
x = theObject.nestedObjectOne.NestedObjectTwo.NestedObjectThree
except AttributeError:
x = None # or whatever value makes the most sense
Without exceptions:
x = getattr(
getattr(
getattr(
theObject, 'nestedObjectOne', None
),
'nestedObjectTwo', None
),
'nestedObjectThree', None
)
(obviously, you can write it on a single line if you don't mind the lack of readability)
Or you could modify the class so that it deals with the case of a non-existent attribute gracefully itself, which can make sense in specific case without being "unpythonic".
For example:
class MyClass:
has_this = 42
def __getattr__(self, item):
if item in self.__dict__:
return self.__dict__[item]
else:
return None
x = MyClass()
print(x.has_this)
print(x.does_not_have_this)
Note that this is a somewhat simplistic and incomplete way to implement this, it's here to show the direction you could be looking in. Of course, you can have MyClass inherit from any other class, to add the behaviour to an existing class.
class Queue:
def __init__(self):
self._contents = []
def enqueue(self, obj):
self._contents.append(obj)
def dequeue(self):
return self._contents.pop(0)
def is_empty(self):
return self._contents == []
class remove_2nd(Queue):
def dequeue(self):
first_item = Queue.dequeue(self)
# Condition if the queue length isn't greater than two
if self.is_empty():
return first_item
else:
# Second item to return
second_item = Queue.dequeue(self)
# Add back the first item to the queue (stuck here)
The remove_2nd class is basically a queue except if the length of the queue is greater than two, then you remove the 2nd item every dequeue. If it isn't then you do the same as a normal queue. I am only allowed to use the methods in the queue to finish remove_2nd.
My algorithm:
If queue is bigger than two:
Lets say my queue is 1 2 3 4
I would first remove the first item so it becomes
2 3 4
I would then remove the 2nd item and that will be the returned value, so then it will be
3 4
I would then add back the first item as wanted
1 3 4
The problem is, I don't know how to add it back. Enqueue puts it at the end, so basically it would be 3 4 1. I was thinking of reversing the 3 4, but I don't know how to do that either. Any help?
Just want to point out, I'm not allowed to call on _contents or allowed to create my own private variable for the remove_2nd class. This should strictly be done using the queue adt
def insert(self,position,element):
self._contents.insert(position,element)
To get the queue back in the right order after removing the first two elements, you'll need to remove all the other elements as well. Once the queue is empty, you can add back the first element and all the other elements one by one.
How exactly you keep track of the values you're removing until you can add them again is a somewhat tricky question that depends on the rules of your assignment. If you can use Python's normal types (as local variables, not as new attributes for your class), you can put them in a list or a deque from the collections module. But you can also just use another Queue instance (an instance of the base type, not your subclass).
Try something like this in your else clause:
second_item = Queue.dequeue(self) # note, this could be written super().dequeue()
temp = Queue()
while not self.is_empty():
temp.enqueue(Queue.dequeue(self))
self.enqueue(first_item)
while not temp.is_empty()
self.enqueue(temp.dequeue())
return second_item
As I commented in the code, Queue.dequeue(self) can be written more "pythonically" using the super builtin. The exact details of the call depend on which version of Python you're using (Python 3's super is much fancier than Python 2's version).
In Python 2, you have to explicitly pass self and your current class, so the call would be super(self, dequeue_2nd).dequeue(). In Python 3, you simply use super().dequeue() and it "magically" takes care of everything (in reality, the compiler figures out the class at compile time, and adds some extra code to let it find self at run time).
For your simple code with only basic inheritance, there's no difference between using super or explicitly looking up the base class by name. But in more complicated situations, using super is very important. If you ever use multiple inheritance, calling overridden methods with super is often the only way to get things to work sanely.
I am trying to set the attribute values of a certain class AuxiliaryClass than is instantiated in a method from MainClass class in the most efficient way possible.
AuxiliaryClass is instantiated within a method of MainClass - see below. However, AuxiliaryClass has many different attributes and I need to set the value of those attributes once the class has been instantiated - see the last 3 lines of my code.
Note: due to design constraints I cannot explain here, my classes only contain methods, meaning that I need to declare attributes as methods (see below).
class AuxiliaryClass(object):
def FirstMethod(self):
return None
...
def NthMethod(self):
return None
class MainClass(object):
def Auxiliary(self):
return AuxiliaryClass()
def main():
obj = MainClass()
obj.Auxiliary().FirstMethod = #some_value
...
obj.Auxiliary().NthMethod = #some_other_value
# ~~> further code
Basically I want to replace these last 3 lines of code with something neater, more elegant and more efficient. I know I could use a dictionary if I was instantiating AuxiliaryClass directly:
d = {'FirstMethod' : some_value,
...
'NthMethod' : some_other_value}
obj = AuxiliaryClass(**d)
But this does not seem to work for the structure of my problem. Finally, I need to set the values of AuxiliaryClass's attributes once MainClass has been instantiated (so I can't set the attribute's values within method Auxiliary).
Is there a better way to do this than obj.Auxiliary().IthMethod = some_value?
EDIT
A couple of people have said that the following lines:
obj.Auxiliary().FirstMethod = #some_value
...
obj.Auxiliary().NthMethod = #some_other_value
will have no effect because they will immediately get garbage collected. I do not really understand what this means, but if I execute the following lines (after the lines above):
print(obj.Auxiliary().FirstMethod())
...
print(obj.Auxiliary().NthMethod())
I am getting the values I entered previously.
To speed things up, and make the customization somewhat cleaner, you can cache the results of the AuxilliaryClass constructor/singleton/accessor, and loop over a dict calling setattr().
Try something like this:
init_values = {
'FirstMethod' : some_value,
:
'NthMethod' : some_other_value,
}
def main():
obj = MainClass()
aux = obj.Auxiliary() # cache the call, only make it once
for attr,value in init_values.items(): # python3 here, iteritems() in P2
setattr(aux, attr, value)
# other stuff below this point
I understand what is happening here: my code has a series of decorators before all methods which allow memoization. I do not know exactly how they work but when used the problem described above - namely, that lines of type obj.Auxiliary().IthMethod = some_value get immediately garbage collected - does not occur.
Unfortunately I cannot give further details regarding these decorators as 1) I do not understand them very well and 2) I cannot transmit this information outside my company. I think under this circumstances it is difficult to answer my question because I cannot fully disclose all the necessary details.
I have this case in Python (with Pyramid framwork), where I'm trying to check for condition.
Here is the code:
if some_condition:
value = self.__parent__.__parent__.__parent__.method()
else:
value = self.__parent__.__parent__.method()
The question is, is there more pythonic way (syntax sugar shortcut) for representing __parent__.__parent__... dynamically?
I know that there is Python syntax like this:
value1, value2, value3 = (None,) * 3
Is there something similar and dynamic for my case?
I searched in Google, in Python documentation, in Reddit source code, in Open Stack source code, and I spend 2 days in searching, so decided to ask here.
If you don't like the parent chain you could always write a helper method to get a node at a given depth. Though this might be less legible.
eg.
def get_parent(item, depth):
original_depth = depth
try:
while depth:
item = item.__parent__
depth -= 1
return item
except AttributeError:
raise AttributeError("No parent node found at depth {}".format(
original_depth-depth))
Usage:
get_parent(self, 3).method()
As far as I know there is no such syntax in python.
However you may indeed implement custom method for obtaining a list of parent resources:
def find_ancestors(resource):
ancestors = [resource]
while hasattr(ancestors[-1], '__parent__'):
ancestors.append(ancestors[-1].__parent__)
return ancestors
Or a method to iterate them:
def iter_ancestors(resource):
yield resource
while hasattr(resource, '__parent__'):
resource = resource.__parent__
yield resource
Also, I'm not sure if such way is the appropriate one. I think you should take a look at find_interface(..) method and somehow manage to define appropriate interfaces for your resources to locate them. Doing such way your code will look like:
value = find_interface(self, ResourceA if some_condition else ResourceB).method()
UPDATE: The code provided by #Dunes in his answer is another good approach to get ancestors by their index.
First, if you guys think the way I'm trying to do things is not Pythonic, feel free to offer alternative suggestions.
I have an object whose functionality needs to change based on outside events. What I've been doing originally is create a new object that inherits from original (let's call it OrigObject()) and overwrites the methods that change (let's call the new object NewObject()). Then I modified both constructors such that they can take in a complete object of the other type to fill in its own values based on the passed in object. Then when I'd need to change functionality, I'd just execute myObject = NewObject(myObject).
I'm starting to see several problems with that approach now. First of all, other places that reference the object need to be updated to reference the new type as well (the above statement, for example, would only update the local myObject variable). But that's not hard to update, only annoying part is remembering to update it in other places each time I change the object in order to prevent weird program behavior.
Second, I'm noticing scenarios where I need a single method from NewObject(), but the other methods from OrigObject(), and I need to be able to switch the functionality on the fly. It doesn't seem like the best solution anymore to be using inheritance, where I'd need to make M*N different classes (where M is the number of methods the class has that can change, and N is the number of variations for each method) that inherit from OrigObject().
I was thinking of using attribute remapping instead, but I seem to be running into issues with it. For example, say I have something like this:
def hybrid_type2(someobj, a):
#do something else
...
class OrigObject(object):
...
def hybrid_fun(self, a):
#do something
...
def switch(type):
if type == 1:
self.hybrid_fun = OrigObject.hybrid_fun
else:
self.fybrid_fun = hybrid_type2
Problem is, after doing this and trying to call the new hybrid_fun after switching it, I get an error saying that hybrid_type2() takes exactly 2 arguments, but I'm passing it one. The object doesn't seem to be passing itself as an argument to the new function anymore like it does with its own methods, anything I can do to remedy that?
I tried including hybrid_type2 inside the class as well and then using self.hybrid_fun = self.hybrid_type2 works, but using self.hybrid_fun = OrigObject.hybrid_fun causes a similar error (complaining that the first argument should be of type OrigObject). I know I can instead define OrigObject.hybrid_fun() logic inside OrigObject.hybrid_type1() so I can revert it back the same way I'm setting it (relative to the instance, rather than relative to the class to avoid having object not be the first argument). But I wanted to ask here if there is a cleaner approach I'm not seeing here? Thanks
EDIT:
Thanks guys, I've given points for several of the solutions that worked well. I essentially ended up using a Strategy pattern using types.MethodType(), I've accepted the answer that explained how to do the Strategy pattern in python (the Wikipedia article was more general, and the use of interfaces is not needed in Python).
Use the types module to create an instance method for a particular instance.
eg.
import types
def strategyA(possible_self):
pass
instance = OrigObject()
instance.strategy = types.MethodType(strategyA, instance)
instance.strategy()
Note that this only effects this specific instance, no other instances will be effected.
You want the Strategy Pattern.
Read about descriptors in Python. The next code should work:
else:
self.fybrid_fun = hybrid_type2.__get__(self, OrigObject)
What about defining it like so:
def hybrid_type2(someobj, a):
#do something else
...
def hybrid_type1(someobj, a):
#do something
...
class OrigObject(object):
def __init__(self):
...
self.run_the_fun = hybrid_type1
...
def hybrid_fun(self, a):
self.run_the_fun(self, a)
def type_switch(self, type):
if type == 1:
self.run_the_fun = hybrid_type1
else:
self.run_the_fun = hybrid_type2
You can change class at runtime:
class OrigObject(object):
...
def hybrid_fun(self, a):
#do something
...
def switch(self):
self.__class__ = DerivedObject
class DerivedObject(OrigObject):
def hybrid_fun(self, a):
#do the other thing
...
def switch(self):
self.__class__ = OrigObject