How can I access a Python object by it's address that I get from id(self.__dict__)?
The background is the following, I want to access one class instance from the other (both classes mimic custom dictionaries):
class1:
def __init__(self):
self.a = class2(self)
# I also tried self.a = class2(self.__dict__) which also does not seem to be a good idea
class2:
def __init__(self, parentobject):
self.parentobject = parentobject
As both class implement dictionaries, I can't iterate over them due to infinite self-referencing
One way to get it working, I thought, would to pass and save only the address of the "parent" class instance.
But in order to access it, I would need to transform somehow the address into something I can access.
Edit: Some people are suggesting that it sounds like a XY problem. To me, a bit too. Therefore, the original problem: I want to implement a nested dictionary. The 'outer' dictionary contains only dictionaries of specific different types. These inner dictionaries hold some values, so:
dictionary["parameter1"]
gives something like {"bla": 42, "blubb":15}
but this custom dictionary also allows for executing functions like
dictionary["parameter1"].evaluate()
This function depends on another parameter parameter2. So to access paramter2, I need somehow the other dictionary that holds parameter2 or I need a reference to the outer dictionary. So, what I tried to do above was to pass self of the outer dictionary to the inner dictionary. To hide this data, I reimplemented __repr__ where I iterate over __dict__ in order to skip the hidden keys. This is where the error is happening. So, I would be happy to find another better solution, but the most obvious one to me was to pass the address instead of the object.
This is a way to do what you're asking, but I'm not sure this works on just any implementation of Python besides the standard CPython, which uses the memory address of objects as their id. That's an implementation detail entirely specific to CPython though. As for whether you should even be trying to do this, I'm not here to judge that:
import ctypes
# create an object
a = [1, 2, 3]
# get the id of the object
b = id(a)
# access the object by its id
c = ctypes.cast(b, ctypes.py_object).value
# print the object
print(c) # output: [1, 2, 3]
Related
Let's say I have this class (simplified for the sake of clarity):
class Foo:
def __init__(self, creator_id):
self._id = get_unique_identifier()
self._owner = creator_id
self._members = set()
self._time = datetime.datetime.now()
get_creator(creator_id).add_foo(self._id)
def add_member(self, mbr_id):
self._members.add(mbr_id)
and I want to make a __deepcopy__() method for it. From what I can tell, the way that these copies are generally made is to create a new instance using the same constructor parameters as the old one, however in my case, that will result in a different identifier, a different time, and a different member set, as well as the object being referenced by the creator's object twice, which will result in breakages.
One possible workaround would be to create the new instance then modify the incorrect internal data to match, but this doesn't fix the issues where the new object's ID will still be present in the creator's data structure. of course, that could be removed manually, but that wouldn't be clean or logical to follow.
Another workaround is to have an optional copy_from parameter in the constructor, but this would add complexity to the constructor in a way that could be confusing, especially since it would only be used implicitly by the object's __deepcopy__() method. This still looks like the best option if there isn't a better way.
#...
def __init__(self, creator_id, copy_from=None):
if isinstance(copy_from, Foo):
# copy all the parameters manually
pass
else:
# normal constructor
pass
#...
Basically, I'm looking for something similar to the copy constructor in C++, where I can get a reference to the original object and then copy across its parameters without having to add unwanted complexity to the original constructor.
Any ideas are appreciated. Let me know if I've overlooked something really simple.
I am currently working on a python-sqlite project, and i am novice to both.
I have created a class that has some attributes declared inside the __init__ method. I need another attribute that will be a list or array, that will contain some of the already declared attributes of the class. What i want is my list to contain just a reference of the original attributes.
I need this structure in order to be able to call these attributes together, to iterate on them, but i want to be able to call them separately, too.
At first I tried to create that list attribute inside the __init__ method, after the rest declarations. When I create an instance, however, and change the initial value of one of the attributes, the attribute in the list is not updated.
Then I tried to create that same list attribute inside another method of the class, instead of inside the init, and call it from inside my code, and it did what I wanted to.
Why does the different approach has different results?
Here is the code at both cases:
Case #1
class Tools():
def __init__(self):
self.name = "defaultname"
self.manufacturer = "defaultmanuf"
self.tooldetails = [self.name, self.manufacturer]
def get_details(self):
return self.tooldetails
Case #2
class Tools():
def __init__(self):
self.name = "defaultname"
self.manufacturer = "defaultmanuf"
def _set_detail_list(self):
self.tooldetails = [self.name, self.manufacturer]
def get_details(self):
_set_detail_list()
return self.tooldetails
And when I create an instance:
tool1 = Tools()
tool1.name = 'abc'
tool1.get_details()
The first case gives me ["defaultname", "defaultmanuf"] while the second gives me ["abc","defaultmanuf"].
My question is what is the reason python gives me different output for each case? It seems like I miss something important about how initialization is working..
dir() and other similar functions or magic methods could be able to give me what i want, but i think they are not flexible enough if you want many different lists with different sets of attributes. Unluckily, introspection doesn't work very well with sqlite string-formatted commands..
Plus i am curious of the way python works, which I believe is very important..
Thanks!!
Case #1
When your list is created within __init__, it contains pointers to 2 strings. But the link between name and tooldetails is irrevocably broken once your list is created. If you update name, tooldetails will not dynamically update, unless you tell Python to explicitly update tooldetails with new data.
Case #2
Here you explicitly tell Python to reconstruct tooldetails via the method _set_detail_list, which is called within get_details. You update name and then tell Python to rebuild the tooldetails list. Therefore, if you update name followed by get_details, your list will be updated.
This is probably very much a beginner question, but I have a question about attributes.
I have a module responsible for Google Docs API actions which contains functions for retrieving information. I would like to be able to refer to certain variables from these functions as attributes.
Here is an example:
Gdocs.py
def getRows():
rows = #action for getting rows
rowsText = #action for converting to text
General.py
import Gdocs
text = Gdocs.getRows.rowstext
I know the basic effect of passing variables can be achieved by just returning the values, but I would like to refer to them as attributes if possible. Simply put, my question is, how can you create an attribute of a function that I can reference in another .py document?
Thanks and sorry if it has been already answered, I did try to search but kept running nto very specific problems.
It sounds as if you want to return a result consisting of multiple parts. Don't use function attributes for this, return a new object that can be addressed via attributes instead. That'd make it thread-safe as well, as function attributes live in the same scope as the function object itself: as a global.
The standard library has a helpful class factory function for just such return values, collections.namedtuple():
from collections import namedtuple
Point = namedtuple('Point', 'x y')
def calculate_coordinates(foo, bar, baz):
return Point(42, 81)
The return value is a tuple subclass, so it can be addressed like a tuple (with indexing), it can be unpacked into separate values, or you can use attributes:
result = calculate_coordinates(spam, ham, eggs)
print result.x, result.y
or
res_x, res_y = calculate_coordinates(spam, ham, eggs)
all work.
While I understand what you said about not wanting a class for each function...
When you have a class, you can apply the #property decorator to functions.
This has the effect of allowing you to effectively create functions that exhibit behaviors but can be called just like attributes. In the following, if you wanted to produce a list of squares based on the input list, you could create a function with a verb-like name called create_list_of_squares(). But in this case, if you really want to keep the API simple and abstract away the mechanics behind the method and simply enable users to access the attributes 'squares', you can use a property decorator, like this...
class SquareList(list):
#property
def squares(self):
return [x ** 2 for x in self]
s = SquareList([1, 2, 3, 4])
print s.squares
which will yield:
[1, 4, 9, 16]
It's a little weird, but you can use staticmethod and classes to get what you want. To wit:
source: zattr2.py
class getRows(object):
#staticmethod
def rows(arg):
return [arg, arg]
#staticmethod
def rowsText(arg):
return repr(arg)
usage:
>>> import zattr2
>>> zattr2.getRows.rowsText('beer')
"'beer'"
See: https://docs.python.org/2/library/functions.html#staticmethod
I want to create a list of class instances that automatically updates itself following a particular condition on the instance attributes.
For example, I have a list of object of my custom class Person() and I want to be able to generate a list that always contains all the married persons, i.e. all persons having the attribute 'MAR_STATUS' equal to 'MARRIED'.
Is this possible at all in Python? I have used a C++ precompiler for microsimulations that had a very handy built-in called "actor_set" which did exactly this. But I have no idea of how it was implemented in C++.
Thank you.
List comprehension:
[person for person in people if person.MAR_STATUS == 'MARRIED']
If you need to assign it to a variable and you want that variable to automatically update on every access, you can put this same code in a lambda, a normal function, or, if your variable is a class member, in a property getter.
It is poor form to have "action at a distance" / mutations / side-effects unless it is very carefully controlled.
That said, imperative language will let you do this, if you really want to, as follows. Here we use python's [property getters and setters]:
MARRIED_SET = set()
def updateMarriedSet(changedPerson):
if hasattr(changedPerson,'married') and changedPerson.married==Person.MARRIED:
MARRIED_SET.add(changedPerson)
else:
MARRIED_SET.discard(changedPerson)
class Person(object):
...
#property
def married(self):
"""The person is married"""
return self._married
#married.setter
def married(self, newStatus):
self._married = newStatus
updateMarriedSet(self)
#married.deleter
def married(self):
del self._married
updateMarriedSet(self)
I can imagine this might, possibly, be useful to ensure accesses to getMarriedPeople() runs in O(1) time rather than amortized O(1) time.
The simple way is to generate the list on the fly e.g., as shown in #sr2222's answer.
As an alternative you could call an arbitrary callback each time MAR_STATUS changes. Use __new__ if Person instances are immutable or make MAR_STATUS a property and call registered callbacks in the setter method (see notifications in traits library for a more complex implementation).
I want to create an object which will hold other objects, and call a method on each of the objects it holds. The end goal is to generate a script for a program. Each object contains a command that can be printed with printCommand(), eventually into a file. My original solution was this:
a = ObjectList()
a.appendObject(Object())
b = ObjectList()
b.appendObject(Object())
listOfObjects = [a, b]
for Object in listOfObjects:
Object.printCommand()
I create a list variable, add objects to thw list, then loop over it issuing the command. While this works, I am primarily doing this excersize to teach myself programming, so I want to know if there is a more elegant solution than writing code to append, pop, etc. items to a list in an object. Since list already contains these functions, i was thinking the correct thing to do would be to extend list:
class Object:
def __init__(self):
self.Command = "Script Command"
def printCommand(self):
print(self.Command)
class ObjectList(list):
def printCommand(self):
for Object in self.LISTCONTENTS:
Object.printCommand()
However, I am at a loss as to how I would tell it to iterate over its own contents. What belongs at self.LISTCONTENTS? Where does a list object store its contents, and how do you access them from a method?
You can just iterate over self:
The superclass methods (i.e., __iter__()) are all present. Saying self in the context of a for statement will cause the appropriate methods to be invoked.
class Object:
def __init__(self):
self.Command = "Script Command"
def printCommand(self):
print(self.Command)
class ObjectList(list):
def printCommand(self):
for Object in self:
Object.printCommand()
lst = ObjectList()
lst.append(Object())
lst.append(Object())
lst.printCommand()
The way this works is list implements __iter__ which is called behind the scenes when iterating over an object:
>>> for e in [1,2,3].__iter__():
... print(e)
...
1
2
3
>>> for e in [1,2,3]:
... print(e)
...
1
2
3
(a) Don't ever create a class called Object, that's far too close to object.
(b) There is absolutely no need to inherit from list, and frankly I doubt the need to use your own class at all.
(c) The normal way to invoke a function on every element of a list is to use map. If you need to map with the same function repeatedly, you can use partial to bind that function to map's first argument.
Now go look at the documentation.