Python ElementTree find first element - python

I need to get the first and only child element of a node and the child is guaranteed to be there. I could write something like this
def get_first(Node):
for x in Node:
return x
But I was hoping for something more elegant. Does anyone know of something?

Have you tried by index?
def get_first(node):
return node[0]

Well, I personally don't see anything wrong with your code. It is clean and will work for any iterable object.
Nevertheless, if you must do away with the for-loop, then you can use next:
def get_first(Node): # Also, Node should be lowercase according to PEP 8
return next(Node)
However, this will only work for iterators. If Node is not an iterator, then you can make it one with iter:
def get_first(Node):
return next(iter(Node))

Related

Recursion in dict

I have a nested dict which looks like this:
There are multiple nestings within the key children. I would like to capture the key branch whenever the key children is present. Because there are multiple children, I would like to do this for each child. Ofcourse, each child can also have further children. This nesting can go upto 7 levels.
To achieve this, I could either write a boneheaded 7-for loop method or use recursion. So I gave recursion a shot and came up with the following code:
def GatherConcepts(header):
if 'children' in header.keys():
if len(header['children']) > 0:
if 'branch' in header.keys():
concepts.append(header['handle'])
if 'children' in header.keys():
for j in range(0, len(header['children'])):
GatherConcepts(header['children'][j])
else:
for i in range(0,len(header['children'])):
GatherConcepts(header['children'][i])
The problem with this code is that it gives me only 2 levels (because I'm calling the function itself 2 times, thereby not using recursion properly), not 7.
How can I improve this to get all the levels?
Any pointers would be highly appreciated.
You have some unnecessary redundancies. If I understand you correctly, you need to add the handles to the list separately from the recursion, because you want to test branch in the parent.
def GatherConcepts(header):
if 'children' in header and 'branch' in header:
for child in header['children']:
concepts.append(child['handle'])
GatherConcepts(child)
You don't need to test the length of header['children'] -- if it's zero then the loop will just not do anything.
In order to get recursion correctly, you can use this simple template for it:
def recursive(variable):
if something:
# base step
return somethingelse
else:
# recursive step
return recursive(somethingelse)
In your case, you can try something like this:
def gather_concepts(header):
# recursive step
if 'branch' in header and 'handle' in header:
concepts.append(header['handle'])
if 'children' in header:
for child in header['children']:
return gather_concepts(child)
# base step
else:
return
You should tweak this code under your needs though, because I haven't tested it myself.

Pythonic shortcut (syntax sugar) for nested self.__parent__.__parent__

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.

How to avoid for-in looping over None in Python

I know I can add some if blocks around to avoid this problem, but I am looking for a best practice or good/nice way to handle this kind of programming problem.
I am looping through the result of a function, without storing the result first in a separate variable; something like this:
for item in mycustimitemgetter.itter():
dosomething()
The itter function is returning None instead of an empty list [], and Python throws an exception per None. This is correct python behavior and nothing's wrong with it. But I'm looking for a best practice solution to:
a) keep the code clean and simple (not storing the result in a var and do if != None, etc..)
b) treat a None return value like an empty list i.e. do not run the loop and silently ignore the fact that function returned a None value.
Perhaps, use the fact that both [] and None evaluate as False, but lists with contents don't:
for item in (mycustimitemgetter.itter() or []):
dosomething()
You have a method called itter() which returns an iterable object. I would say that given the name of the function, it's reasonable to say "the returned value should always be iterable". So, if you're returning a list, you should return an empty list if you have no values.
Code there to be executed. There is nothing wrong with adding:
if retval is None:
return []
return retval
or
return retval or []
to the end of your itter() implementation, depending on the types in use.
Consider this: you wrote the code and you're facing this problem. What about someone else who's trying to use your code without knowing what you know. What do they expect?
Alternatively you should use Generators (if suitable). They contain a 'next' method (see the docs at the link), which you can return false if there are no values.

Python default values for class member function parameters set to member variables

I am running into a problem writing recursive member functions in Python. I can't initialize the default value of a function parameter to be the same value as a member variable. I am guessing that Python doesn't support that capability as it says self isn't defined at the time I'm trying to assign the parameter. While I can code around it, the lack of function overloading in Python knocks out one obvious solution I would try.
For example, trying to recursively print a linked list I get the following code for my display function;
def display(self,head = -1):
if head == -1:
head = self.head
if not head:
return
print head,
self.display(head.link)
While this code works, it is ugly.
The main function looks like this:
def main():
l = List();
l.insert(3);
l.insert(40);
l.insert(43);
l.insert(45);
l.insert(65);
l.insert(76);
l.display()
if __name__ == "__main__":
main()
If I could set the display function parameter to default to self.head if it is called without parameters then it would look much nicer. I initially tried to create two versions of the function, one that takes two parameters and one that takes one but as I said, Python doesn't support overloading. I could pass in an argument list and check for the number of arguments but that would be pretty ugly as well (it would make it look like Perl!). The trouble is, if I put the line
head = self.head
inside the function body, it will be called during every recursive call, that's definitely not the behavior I need. None is also a valid value for the head variable so I can't pass that in as a default value. I am using -1 to basically know that I'm in the initial function call and not a recursive call. I realize I could write two functions, one driving the other but I'd rather have it all self contained in one recursive function. I'm pretty sure I'm missing some basic pythonic principle here, could someone help me out with the pythonic approach to the problem?
Thanks!
I don't really see what's wrong with your code. If you chose a falsy default value for head, you could do: head = head or self.head which is more concise.
Otherwise, this is pretty much what you have to do to handle default arguments. Alternatively, use kwargs:
def display(self,**kwargs):
head = kwargs.get("head", self.head)
if not head:
return
print head,
self.display(head=head.link) # you should always name an optional argument,
# and you must name it if **kwargs is used.

Scope of next() in Python

I am trying to use the next function on an iterator, however, I have a local variable in the same scope that is also named next. The obvious solution is to rename the local variable, however, I'm fairly new to Python so I'm curious to learn how to prefix the next function so I achieve the desired behavior.
The code I'm using looks something like this:
for prev, curr, next in neighborhood(list):
if (prev == desired_value):
print(prev+" "+next)
desired_value = next(value_iterator)
Note that I'm using Python 3.2.
You can use __builtins__.next to refer to the next built-in function.
for prev, curr, next in neighborhood(list):
if (prev == desired_value):
print(prev+" "+next)
desired_value = __builtins__.next(value_iterator)
However, as you point out, the obvious solution is to use a different name for your variable.
You can call the next() method of the iterator directly. You lose, however, the ability to suppress StopIteration at the end of the iteration in favor of seeing a default value.
desired_value = value_iterator.next()
Note that in Python 3, this method has been renamed __next__().
Before you assign something to next, use something like:
real_next = next

Categories