What is the difference between getattr() and calling the attribute? - python

Here is a code I have written. I presumed both of them to return the same answer but they don't! How are they different?
from collections import deque
d = deque()
for _ in range(int(input())):
method, *n = input().split()
getattr(d, method)(*n)
print(*d)
and
from collections import deque
d = deque()
for _ in range(int(input())):
method, *n = input().split()
d.method(*n)
print(*d)

getattr(...) will get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
Where as d.method(*n) will try to lookup the method named method in deque object result in AttributeError: 'collections.deque' object has no attribute 'method'
>>> from collections import deque
>>> d = deque()
>>> dir(d) # removed dunder methods for readability
[
"append",
"appendleft",
"clear",
"copy",
"count",
"extend",
"extendleft",
"index",
"insert",
"maxlen",
"pop",
"popleft",
"remove",
"reverse",
"rotate",
]
>>> method = "insert"
>>> d.method
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'collections.deque' object has no attribute 'method'
>>> insert_method = getattr(d, method)
>>> insert_method
<built-in method insert of collections.deque object at 0x000001E5638AC0>
>>> help(insert_method)
Help on built-in function insert:
insert(...) method of collections.deque instance
D.insert(index, object) -- insert object before index
>>> insert_method(0, 1)
>>> d
deque([1])

Related

How do I clear a Python threading.local object?

How can I clear all the attributes off an instance of Python's threading.local()?
You can clear it's underlying __dict__:
>>> l = threading.local()
>>> l
<thread._local object at 0x7fe8d5af5fb0>
>>> l.ok = "yes"
>>> l.__dict__
{'ok': 'yes'}
>>> l.__dict__.clear()
>>> l.__dict__
{}
>>> l.ok
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'thread._local' object has no attribute 'ok'
Accessing the __dict__ directly is specifically called out as a valid way to interact with the local object in the _threading_local module documentation:
Thread-local objects support the management of thread-local data.
If you have data that you want to be local to a thread, simply create
a thread-local object and use its attributes:
>>> mydata = local()
>>> mydata.number = 42
>>> mydata.number
42
You can also access the local-object's dictionary:
>>> mydata.__dict__
{'number': 42}
>>> mydata.__dict__.setdefault('widgets', [])
[]
>>> mydata.widgets
[]

"TypeError: 'unicode' object does not support item assignment" in dictionaries

I am trying to build/update a dictionary. I have nicknames as keys in temp_dict and looking for ids to add.
Excerpt form my code. I think it is enough for you to see my mistake.
d1 = {u'status': u'ok', u'count': 1, u'data': [{u'nickname': u'45sss', u'account_id': 553472}]}
temp_dict = {}
for key, value in d1.iteritems():
if "data" == key:
for dic2 in value:
x = dic2['nickname']
y = dic2['account_id']
temp_dict[x] = y;
My error:
Traceback (most recent call last):
File "untitled.py", line 36, in <module>
get_PlayerIds_Names_WowpApi_TJ_() #Easy going. Some issues with case letters.
File "g:\Desktop\Programming\WOWP API\functions.py", line 44, in get_PlayerIds_Names_WowpApi_TJ_
check_missing_player_ids(basket)
File "g:\Desktop\Programming\WOWP API\functions.py", line 195, in check_missing_player_ids
temp_dict[x] = y;
TypeError: 'unicode' object does not support item assignment
There are multiple SO entries regarding the same error. But no are connected to such dictionary manipulation.
Most likely you have put unicode string in temp_dict somewhere:
>>> temp_dict = u''
>>> dic2 = {u'nickname': u'45sss', u'account_id': 553472}
>>> x = dic2['nickname']
>>> y = dic2['account_id']
>>> temp_dict[x] = y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'unicode' object does not support item assignment
init it with empty dict and all will work:
>>> temp_dict = {}
>>> temp_dict[x] = y
>>> temp_dict
{u'45sss': 553472}

in python ,if i edit this: type("myclass", (foo,), {"bar()", barbar}, how can i access the attribute "bar()"

>>> FooChild = type("FooChild", (Foo,), {"echobar()":echo_bar})
>>> FooChild().echobar()
Traceback (most recent call last):
File "<pyshell#214>", line 1, in <module>
FooChild().echobar()
AttributeError: 'FooChild' object has no attribute 'echobar'
>>> FooChild().echobar
Traceback (most recent call last):
File "<pyshell#215>", line 1, in <module>
FooChild().echobar
AttributeError: 'FooChild' object has no attribute 'echobar'
>>> hasattr(FooChild, "echobar()")
True
>>> FooChild().echobar()()
Traceback (most recent call last):
File "<pyshell#217>", line 1, in <module>
FooChild().echobar()()
AttributeError: 'FooChild' object has no attribute 'echobar'
Remove those parentheses:
FooChild = type("FooChild", (Foo,), {"echobar":echo_bar})
The name of a function is without the parentheses. Appending them means to call the function. Without the parentheses you have a reference on the function itself (e. g. for passing a function to things like sort or map).
echobar() is an invalid identifier in python, so you can't access it directly i.e using the dot syntax:
>>> FooChild = type("FooChild", (Foo,), {"echobar()":10})
Use __dict__ or getattr:
>>> FooChild.__dict__['echobar()']
10
>>> getattr(FooChild, 'echobar()')
10
If you want to use it as an attribute then simply get rid of the parenthesis:
>>> FooChild = type("FooChild", (Foo,), {"echobar":10})
>>> FooChild.echobar
10
If you want to use it as a method, then:
>>> def echobar(self):return 10
>>> FooChild = type("FooChild", (Foo,), {'echobar':echobar})
>>> FooChild().echobar()
10
If you pretend to have fancy function with name echobar() in you class, only mean of accessing it is getattr:
class Foo(object):pass
echo_bar =lambda *a: 'bar'
FooChild = type("FooChild", (Foo,), {"echobar()":echo_bar})
print getattr(FooChild(), 'echobar()')()
# bar

Retrieving attributes of elements in Python using libxml2

I'm writing my first Python script using libxml2 to retrieve data from an XML file. The file looks like the following:
<myGroups1>
<myGrpContents name="ABC" help="abc_help">
<myGrpKeyword name="abc1" help="help1"/>
<myGrpKeyword name="abc2" help="help2"/>
<myGrpKeyword name="abc3" help="help3"/>
</myGrpContents>
</myGroups1>
There are many similar groups in the file. My intention is to get the attributes "name" and "help" and put them in a different format into another file. But I'm only able to retrieve till myGroups1 element using the following code.
doc = libxml2.parseFile(cmmfilename)
root2 = doc.children
child = root2.children
while child is not None:
if not child.isBlankNode():
if child.type == "element":
print "\t Element ", child.name, " with ", child.lsCountNode(), "child(ren)"
print "\t and content ", repr(child.content)
child = child.next
How can I iterate deeper to the elements and get the attributes? Any help in this would be deeply appreciated.
python. how to get attribute value with libxml2 is probably the kind of answer you're looking for.
When faced with a problem like this, when I'd rather not read the docs for some reason, exploring a library interactively like this can be helpful - I suggest you use an interactive python repl (I like bpython) to try this. Here's my session in which I came up with a solution:
>>> import libxml2
>>> xml = """<myGroups1>
... <myGrpContents name="ABC" help="abc_help">
... <myGrpKeyword name="abc1" help="help1"/>
... <myGrpKeyword name="abc2" help="help2"/>
... <myGrpKeyword name="abc3" help="help3"/>
... </myGrpContents>
... </myGroups1>"""
>>> tree = libxml2.parseMemory(xml, len(xml)) # I found this method by looking through `dir(libxml2)`
>>> tree.children
<xmlNode (myGroups1) object at 0x10aba33b0>
>>> a = tree.children
>>> a
<xmlNode (myGroups1) object at 0x10a919ea8>
>>> a.children
<xmlNode (text) object at 0x10ab24368>
>>> a.properties
>>> b = a.children
>>> b.children
>>> b.properties
>>> b.next
<xmlNode (myGrpContents) object at 0x10a921290>
>>> b.next.content
'\n \n \n \n'
>>> b.next.next.content
'\n'
>>> b.next.next.next.content
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'content'
>>> b.next.next.next
>>> b.next.properties
<xmlAttr (name) object at 0x10aba32d8>
>>> b.next.properties.children
<xmlNode (text) object at 0x10ab40f38>
>>> b.next.properties.children.content
'ABC'
>>> b.next.properties.children.name
'text'
>>> b.next.properties.next
<xmlAttr (help) object at 0x10ab40fc8>
>>> b.next.properties.next.name
'help'
>>> b.next.properties.next.content
'abc_help'
>>> list(tree)
[<xmlDoc (None) object at 0x10a921248>, <xmlNode (myGroups1) object at 0x10aba32d8>, <xmlNode (text) object at 0x10aba3878>, <xmlNode (myGrpContents) object at 0x10aba3d88>, <xmlNode (text) object at 0x10aba3950>, <xmlNode (myGrpKeyword) object at 0x10aba3758>, <xmlNode (text) object at 0x10aba3320>, <xmlNode (myGrpKeyword) object at 0x10aba3f38>, <xmlNode (text) object at 0x10aba3560>, <xmlNode (myGrpKeyword) object at 0x10aba3998>, <xmlNode (text) object at 0x10aba33f8>, <xmlNode (text) object at 0x10aba38c0>]
>>> good = list(tree)[5]
>>> good.properties
<xmlAttr (name) object at 0x10aba35f0>
>>> good.prop('name')
'abc1'
>>> good.prop('help')
'help1'
>>> good.prop('whoops')
>>> good.hasProp('whoops')
>>> good.hasProp('name')
<xmlAttr (name) object at 0x10ab40ef0>
>>> good.hasProp('name').content
'abc1'
>>> for thing in tree:
... if thing.hasProp('name') and thing.hasProp('help'):
... print thing.prop('name'), thing.prop('help')
...
...
...
ABC abc_help
abc1 help1
abc2 help2
abc3 help3
Because it's bpython, I cheated a little bit - there's a rewind key, so I mistyped more than this, but otherwise this is pretty close.
Haven't used libxml2, but dived in to the case and found this,
try either,
if child.type == "element":
if child.name == "myGrpKeyword":
print child.prop('name')
print child.prop('help')
or
if child.type == "element":
if child.name == "myGrpKeyword":
for property in child.properties:
if property.type=='attribute':
# check what is the attribute
if property.name == 'name':
print property.content
if property.name == 'help':
print property.content
Refer http://ukchill.com/technology/getting-started-with-libxml2-and-python-part-1/
update:
try a recursive function
def explore(child):
while child is not None:
if not child.isBlankNode():
if child.type == "element":
print element.prop('name')
print element.prop('help')
explore(child.children)
child = child.next
doc = libxml2.parseFile(cmmfilename)
root2 = doc.children
child = root2.children
explore(child)

'str' object has no attribute '__dict__'

I want to serialize a dictionary to JSON in Python. I have this 'str' object has no attribute 'dict' error. Here is my code...
from django.utils import simplejson
class Person(object):
a = ""
person1 = Person()
person1.a = "111"
person2 = Person()
person2.a = "222"
list = {}
list["first"] = person1
list["second"] = person2
s = simplejson.dumps([p.__dict__ for p in list])
And the exception is;
Traceback (most recent call last):
File "/base/data/home/apps/py-ide-online/2.352580383594527534/shell.py", line 380, in post
exec(compiled_code, globals())
File "<string>", line 17, in <module>
AttributeError: 'str' object has no attribute '__dict__'
How about
s = simplejson.dumps([p.__dict__ for p in list.itervalues()])
What do you think [p.__dict__ for p in list] does?
Since list is not a list, it's a dictionary, the for p in list iterates over the key values of the dictionary. The keys are strings.
Never use names like list or dict for variables.
And never lie about a data type. Your list variable is a dictionary. Call it "person_dict` and you'll be happier.
You are using a dictionary, not a list as your list, in order your code to work you should change it to a list e.g.
list = []
list.append(person1)
list.append(person2)

Categories

Resources