Print an object's attributes like json.dumps prints a dict [duplicate] - python

This question already has answers here:
Is there a built-in function to print all the current properties and values of an object?
(30 answers)
Closed 7 years ago.
EDIT: a solution is in this answer: How to use a dot “.” to access members of dictionary?
When using a dict:
d = dict()
d['param1'] = 17
d['param2'] = 3
it's easy to print it with print json.dumps(d). When using an object / class:
class z:
pass
z.param1 = 17
z.param2 = 3
I can't manage to print all the attributes of z, neither with print json.dumps(z), nor with print z. How to do it?
Sidenote but important: why do I want to use a class / object to store parameters, when it would be logical to use a dict? Because z.param1 is much shorter and handy to write than z['param1'], especially with my (french) keyword [, ], 'are quit long to write because ALT+GR+5 (let's say 2 seconds instead of 0.5, but this really matters when you have a long code with many variables)

You may simply use __dict__ on a class instance to get the attributes in the form of dict object as:
>>> z.__dict__
>>> {'param1': 17, '__module__': '__main__', 'param2': 3, '__doc__': None}
However, if you need to remove the __xxx__ inbuilt methods then you may need to specify the __str__ method inside the class.

Related

How to call a function within an attribute? [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 3 years ago.
I have a Python class that have attributes named: date1, date2, date3, etc.
During runtime, I have a variable i, which is an integer.
What I want to do is to access the appropriate date attribute in run time based on the value of i.
For example,
if i == 1, I want to access myobject.date1
if i == 2, I want to access myobject.date2
And I want to do something similar for class instead of attribute.
For example, I have a bunch of classes: MyClass1, MyClass2, MyClass3, etc. And I have a variable k.
if k == 1, I want to instantiate a new instance of MyClass1
if k == 2, I want to instantiate a new instance of MyClass2
How can i do that?
EDIT
I'm hoping to avoid using a giant if-then-else statement to select the appropriate attribute/class.
Is there a way in Python to compose the class name on the fly using the value of a variable?
You can use getattr() to access a property when you don't know its name until runtime:
obj = myobject()
i = 7
date7 = getattr(obj, 'date%d' % i) # same as obj.date7
If you keep your numbered classes in a module called foo, you can use getattr() again to access them by number.
foo.py:
class Class1: pass
class Class2: pass
[ etc ]
bar.py:
import foo
i = 3
someClass = getattr(foo, "Class%d" % i) # Same as someClass = foo.Class3
obj = someClass() # someClass is a pointer to foo.Class3
# short version:
obj = getattr(foo, "Class%d" % i)()
Having said all that, you really should avoid this sort of thing because you will never be able to find out where these numbered properties and classes are being used except by reading through your entire codebase. You are better off putting everything in a dictionary.
For the first case, you should be able to do:
getattr(myobject, 'date%s' % i)
For the second case, you can do:
myobject = locals()['MyClass%s' % k]()
However, the fact that you need to do this in the first place can be a sign that you're approaching the problem in a very non-Pythonic way.
OK, well... It seems like this needs a bit of work. Firstly, for your date* things, they should be perhaps stored as a dict of attributes. eg, myobj.dates[1], so on.
For the classes, it sounds like you want polymorphism. All of your MyClass* classes should have a common ancestor. The ancestor's __new__ method should figure out which of its children to instantiate.
One way for the parent to know what to make is to keep a dict of the children. There are ways that the parent class doesn't need to enumerate its children by searching for all of its subclasses but it's a bit more complex to implement. See here for more info on how you might take that approach. Read the comments especially, they expand on it.
class Parent(object):
_children = {
1: MyClass1,
2: MyClass2,
}
def __new__(k):
return object.__new__(Parent._children[k])
class MyClass1(Parent):
def __init__(self):
self.foo = 1
class MyClass2(Parent):
def __init__(self):
self.foo = 2
bar = Parent(1)
print bar.foo # 1
baz = Parent(2)
print bar.foo # 2
Thirdly, you really should rethink your variable naming. Don't use numbers to enumerate your variables, instead give them meaningful names. i and k are bad to use as they are by convention reserved for loop indexes.
A sample of your existing code would be very helpful in improving it.
to get a list of all the attributes, try:
dir(<class instance>)
I agree with Daenyth, but if you're feeling sassy you can use the dict method that comes with all classes:
>>> class nullclass(object):
def nullmethod():
pass
>>> nullclass.__dict__.keys()
['__dict__', '__module__', '__weakref__', 'nullmethod', '__doc__']
>>> nullclass.__dict__["nullmethod"]
<function nullmethod at 0x013366A8>

How to pass a reference to a value inside a dictionary? [duplicate]

This question already has answers here:
Passing an integer by reference in Python
(13 answers)
Closed 8 months ago.
Suppose we have a dictionary:
some_dict = {
"first": 11111,
"second": {
"second_1": 22222,
"second_2": 232323,
"second_3": 99999
}
}
if I create a new variable a with value some_dict["second"], then it will be a reference:
ref = some_dict["second"]
Accordingly, if I change the value of the nested dictionary second in some_dict, then it will also change in ref:
some_dict["second"]["second_1"] = "not a second_1"
print(ref)
Output:
{'second_1': 'not a second_1', 'second_2': 232323, 'second_3': 99999}
How can I create the same reference, but not to a nested dictionary, but to a value, such as int or str?
Like this:
ref = some_dict["second"]["second_1"]
some_dict["second"]["second_1"] = "not a second_1"
print(ref)
Estimated output:
not a second_1
The quick-and-dirty answer is to put it into a one-element list.
my_original_int = [0]
my_ref_to_int = my_original_int
Now modifications to (the integer value inside) either variable will reflect in the other.
But, that's horrible coding practice. At minimum, that should be encapsulated into a class.
class Cell:
def __init__(self, value):
self.value = value
my_original_int = Cell(0)
my_ref_to_int = my_original_int
Then either can be accessed or modified through the .value member.
Even better would be to make a specific class to your use case. Ask yourself why you're wanting to alias integers. "My integer represents data in a JSON file somewhere" is a great answer, and it suggests that there should be a MyJsonData class somewhere that has integer fields, and you should be passing around references to that instead of to the integers.
Basically, make your data usage as explicit as possible, and your code will be more readable and intuitive. I even go so far as to try to avoid aliasing lists and dictionaries. If I find myself needing such behavior, it's often about time for me to encapsulate that list in a class with a more specific name and detailed docstring.

Is there a way to change the attribute of an object assigned to the attribute of another object? [duplicate]

This question already has answers here:
Python Class dynamic attribute access
(2 answers)
Closed 4 years ago.
I'd like to change the attribute of an object that has been assigned as an attribute of another object.
cageNumber = int(input('Cage number: '))
mouseNumber = int(input('Mouse number: '))
mouseID = f'm{mouseNumber}'
setattr(cages[cageNumber].mouseID, 'sacrificed', True)
The cage is an instance of a class and each cage has 5 attributes. Each mouse is an instance of a class and they are assigned as the attributes of the cage object. The cages are contained in a dictionary.
My cage has no attribute named mouseID, but it DOES have 5 attributes named
m1, m2, m3, m4, and m5. These are solved by mouseID = f'm{mouseNumber}'.
I'd like to do something like this: cage[101].m3.sacrificed = True for each of 5 mice
(m1 - m5).
If I understand what you're looking for, you need to use a call to getattr() to get the attribute by name as a string. Also, I don't really see a reason to use setattr() here.
getattr(cages[cageNumber], mouseID).sacrificed = True
Although if you're doing this sort of thing a lot (and even if you're not), it would probably be less cumbersome to put m1, m2, etc. into a list or dict for easier indexing, so you can instead do something like:
cages[cageNumber].mice[mouseID].sacrificed = True

Do stuff with variable that has the same name of a string [duplicate]

This question already has answers here:
How to use string value as a variable name in Python? [duplicate]
(3 answers)
How do I create variable variables?
(17 answers)
Closed 4 years ago.
let's say I have a variable called "x" and a string that has the value of "x" (string1 = "x"). How do I do stuff with the variable through the string?
For example change the variable's value or call a method if it's an object?
Thanks in advance
Variables are available through dictionaries locals() and globals(). If you want to access a particular variable by it's spring name, you can do e.g.
>>> my_var = 'hello'
>>> x = 'my_var'
>>> locals()[x]
'hello'
You can also assign back to the variable using this approach, e.g.
>>> my_var = 'hello'
>>> x = 'my_var'
>>> locals()[x] = 'something else'
>>> my_var
'something else'
Since functions are objects in Python, you can access any locally available functions in the same manner to call them.
>>> def my_test_function(n):
>>> return n*8
Accessing the method and calling it.
>>> locals()['my_test_function'](4)
32
For accessing attributes of objects by their name you can use getattr(), and setattr() to set them. For example, creating an object with a single property called your_prop.
class Example:
your_prop = 2
a = Example()
The value is available via your_prop.
>>> a.your_prop
2
The property can be accessed via name using getattr
>>> getattr(a, 'your_prop')
2
The property can be set using setattr:
>>> setattr(a, 'your_prop', 5)
>>> a.your_prop
5
Ok, let's suppose that you have lots of different functions: Aoo(), Boo(), Coo()... and let's suppose that you want to specify which of them to call via command line argument.
Now, that argument will be a string, so you need to call a function through its name, but you do not know in advance the name of the function.
One possible solution is to use exec():
def boo():
print("boo function")
def coo():
print("coo function")
Now:
argument = "boo"
exec(argument + "()")
>>> boo function
and
argument = "coo"
exec(argument + "()")
>>> coo function
It depends what you're trying to do, but you can scoop up whatever x is pointing to with locals() or globals():
def x(k):
return k + 1
string1 = "x"
the_function_x = locals()[string1]
print(the_function_x(3))
outputs 4 (it called the x function by utilizing string1).

python select a function based on the value in a dictionary [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 6 years ago.
I want to select a function based on the value of a dictionary:
dict = {"func_selector":"func1", "param_value":"some_value"}
# defined a function
def func1(param):
# some function code
Now, I want to select the function based on the value of some key, so that it can achieve something like:
# calling a function based on some dict value
dict["func_selector"](dict["param_value"])
The syntax is probably wrong, but I am wondering if it is possible to do that in Python or something similar.
Try storing the value of the function in the dictionary, instead of its name:
def func1(param):
print "func1, param=%r" % (param,)
d = {"func_selector":func1, "param_value": "some value"}
Then you can say:
>>> d['func_selector'](d['param_value'])
func1, param='some value'
The best approach IMO is do it like this
def func1(param):
#code
some_value = ... #The value you need
my_dict = {"func_selector": func1, "param_value": some_value }
And then
my_dict["func_selector"](my_dict["param_value"])
Now, if you only have the name of the function you need to call getattr
And call it
getattr(my_class, my_dict["func_selector"])(my_dict["param_value"])
my_class is the class which contains the method. If it's not in a class I think you can pass self

Categories

Resources