Getting value of a functions attribute from a string - python

I am trying to log with syslog. I have a string with the facility in it. In this case "LOG_LOCAL0". I want to use this string to access syslog.LOG_LOCAL0, which is an int of value 128. If this was a function I would use getattr() but I do not know how do do it for something that is not callable like an int, how do I?
Basically I want to call syslog.LOG_LOCAL0 but have the "LOG_LOCAL0" as a string so I can't.

If you're trying to set a value you want setattr(object, name, value) (note there's no underscore btw). So you could do:
setattr(syslog, "LOG_LOCAL0", "The log value")
If you want to use the value then getattr is still appropriate
getattr(syslog, "LOG_LOCAL0") # syslog.LOG_LOCAL0 for all intents and purposes

You can use __dict__ it returns a dictionary of all functions and variables in the class , and then use the variable you want to get as key, to get its value.
Example -
>>> class CA:
... i = 15
... def hello(self):
... print("Hello")
...
>>> CA.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'CA' objects>, '
>>> CA.__dict__['i']
15
In your case maybe -
syslog.__dict__['LOG_LOCAL0']
Though a footnote from here -
Except for one thing. Module objects have a secret read-only attribute called dict which returns the dictionary used to implement the module’s namespace; the name dict is an attribute but not a global name. Obviously, using this violates the abstraction of namespace implementation, and should be restricted to things like post-mortem debuggers.

Related

How to get the name of a value in an enum declaration?

In Python3.7.7, I would like to use the name of an Enum value in the declaration of another value of the same Enum.
My first try:
from enum import Enum
class test(Enum):
value1 = "a"
value2 = value1.name + "b"
This returns an AttributeError: 'str' object has no attribute 'name'. I tried using self.value1 and test.value1 instead and both return a NameError.
I could just use value2 = "value1b" but I fear that it would give me weird errors down the line if I ever change the name of value1 and forget some places instead of an immediate error because of an undefined variable.
During Enum class creation the values are just values -- they are not converted to Enum members until the end of the class definition.
There is nothing currently in the class definition machinery to support your use-case; however, you can use the functional syntax to generate your Enum:
# some code to calculate your names and values (not shown)
# that results in
members = (('value1', 'a'),('value2', 'value1a'))
test = Enum('test', members)
Which results in:
>>> list(test)
[<test.value1: 'a'>, <test.value2: 'value1a'>]
What you try to achieve is not simple, because you can only directly reference from a variable to the value, not vice versa.
I think the easiest solution is using Python3.8+ and using the debugging feature of f-strings (emphasis mine):
To display both the expression text and its value after evaluation, (useful in debugging), an equal sign '=' may be added after the expression.
So the code would turn into:
from enum import Enum
class test(Enum):
value1 = "a"
value2 = f"{value1=}".split("=")[0] + "b"
Other solutions, also working with Python3.7- can be found here. But they are more complicated to implement.

How can I call a method from a name string in Python?

I am using an API to call specific information from a website. I need to be able to parse through the list to utilize the functions. Example:
list = ['doThis','doThat']
for item in list:
sampleobject.item
The issue is when I use this, I get an error saying "sampleobject has no attribute 'item'".
Is there a way that I can pull the quote out of the string to do this?
Try:
methods = ['doThis','doThat']
for method_name in methods:
method = getattr(sampleobject, method_name)
method()
Though it would be easier to do:
sampleobject.doThis()
sampleobject.doThat()
You can call getattr(sampleobject, item) to get the content of a property with the name equal to what is stored in item, which is an element from your list.
I think the problem is not about quotes at all. The problem is that syntax object.member means: evaluate a property named member that is stored in a variable named object. And you expect it to mean: evaluated a property with the name stored in member.

Python - Calling a class as a parameter [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 5 years ago.
I'm quite new in Python, but googling around did not match any answer for it .
I created a module, containing 10 GUI buttons classes. To use a button I write in code ButtonLib.TypeA(**kwargs), ButtonLib.TypeB(**kwargs) and so on.
kwargs is same for all buttons.
Buttons ( amount and type ) are selected by user (stored in button_type_vector) and not known in advance.
I wish to know if there is a way writing code more efficiently rather than:
for x in button_type_vector:
if x == 'TypeA':
ButtonLib.TypeA(**kwargs)
elif x== 'TypeB' :
ButtonLib.TypeB(**kwargs)
and so on.
by efficiently I mean something like:
for x in button_type_vector:
ButtonLib.x(**kwargs)
thnks
You can use the getattr built-in function to access attributes of an object using strings:
Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.
for x in button_type_vector:
getattr(ButtonLib, x)(**kwargs)
As mentioned by #MadPyhisist, modules are not some kind of magical object, and thus can be used with like any normal object could be getattr.
You could define a dictionary (preferably inside your module):
buttons = {
"TypeA": TypeA,
"TypeB": TypeB,
…
}
and then call the entry:
ButtonLib.buttons[x](**kwargs)
If your button classes have a function returning their name, you could also define the dictionary like this:
buttons = {
button_type.name: button_type
for button_type in [TypeA, TypeB, …]
}
More advanced: Python stores the name of a class in .__name__.
Even more advanced: You could get the elements of the module with getattr(ButtonLib, name). But this might impair readability.

Python - How to call an instance from a given string?

I want to call the function bar() from the instance foo, just like this:
foo.bar()
But both instance and function names come from a given string. I tried getattr but it just let me use a string for the function, not the instance:
strbar = 'bar'
getattr(foo, strbar)()
What I want to do is something like:
strfoo = 'foo'
strbar = 'bar'
getattr(strfoo, strbar)()
But it gives me:
AttributeError: 'str' object has no attribute 'bar'
I know a dictionary could be an option, but that makes me write a really long dictionary.
The best way would be to have a dictionary or a similar structure.
However you could use eval which is evil. Or you can get your instance from the locals() dictionary:
getattr(locals()[instance_name], attribute_name)
I would think about redesigning your code. There must be a better solution as eval or locals ... like a dictionary ...

How do I tell what type of data is inside python variable?

I have a list of variables.. inside the list are strings, numbers, and class objects. I need to perform logic based on each different type of data. I am having trouble detecting class objects and branching my logic at that point.
if(type(lists[listname][0]).__name__ == 'str'): # <--- this works for strings
elif(type(lists[listname][0]).__name__ == 'object'): <--- this does not work for classes
in the second line of code above, the name variable contains "Address" as the class name. I was hoping it would contain "class" or "object" so I could branch my program. I will have many different types of objects in the future, so it's a bit impractical to perform logic on every different class name, "Address" "Person" etc
please let me know if my question needs clarification.
thanks!!
FYI: it also makes a difference if its a new-style class or not:
# python
type(1).__name__
'int'
type('1').__name__
'str'
class foo(object):
pass
type(foo()).__name__
'foo'
class bar:
pass
type(bar()).__name__
'instance'
If you can make sure they're all new-style classes, your method will determine the real type. If you make them old-style, it'll show up as 'instance'. Not that I'm recommending making everything all old-style just for this.
However, you can take it one step further:
type(bar().__class__).__name__
'classobj'
type(foo().__class__).__name__
'type'
And always look for 'classobj' or 'type'. (Or the name of the metaclass, if it has one.)
I think you want the isinstance function.
if isinstance(o, ClassName):
However, you'll need to first verify that o is an object, you can use type for that.
It's common in Python to use exception handling to decide which code path to take; inspecting the exact type of an object (with isinstance()) to decide what to do with it is discouraged.
For example, say that what you want to do is, if it's a string, print it in "title case", and if it's an object, you want to call a particular method on it. So:
try:
# is it an object with a particular method?
lists[listname][0].particularMethod()
except AttributeError:
# no, it doesn't have particularMethod(),
# so we expect it to be a string; print it in title case
print lists[listname][0].title()
If you are only interested in handling two types specifically, you could test for them explicitly using isinstance and then handle the leftovers:
import numbers
for item in list:
if isinstance(item, basestring): # (str, unicode)
do_string_thing(item)
elif isinstance(item, numbers.Real): # (int, float, long)
do_number_thing(item)
else:
do_object_thing(item)

Categories

Resources