Python is a safe and elegant way to set a variable from a function that can return None

I'm looking for a more elegant way of declaring a variable value, where a function can return None , and there are chains after the function call.

In the example below, I use BeautifulSoup to pass an HTML document, and if the item I'm looking for is not found, the initial function call returns None . Chained methods interrupt code because .string not a None object method.

That all makes sense, but I wonder if there is a cleaner way to write these variable declarations that won't break into a None value.

 # I want to do something like this but it throws error if soup.find returns # none because .string is not a method of None. title = soup.find("h1", "article-title").string or "none" # This works but is both ugly and inefficient title = "none" if soup.find("h1", "article-title") is None else soup.find("h1", "article-title").string # So instead I'm using this which feels clunky as well title = soup.find("h1", "article-title") title = "none" if title is None else title.string 

The best way?

+6
source share
3 answers

You can use the getattr built-in function to provide a default value if the desired attribute is not found in the given object

 title = getattr(soup.find("h1", "article-title"), "string", "none") 

Alternatively you can use try statement :

 try: title = soup.find("h1", "article-title").string except AttributeError: title = "none" 

The first method is more elegant, in my opinion.

+1
source

I like Shashank's answer, but this might work for you too:

 class placeholder: string = "none" title = (soup.find("h1", "article-title") or placeholder).string 
+4
source

This behavior of Beautiful Soup really annoys me. Here is my solution: http://soupy.readthedocs.org/en/latest/

This smooths out a lot of edges in BeautifulSoup, allowing you to write queries like

 dom.find('h1').find('h2').find('a')['href'].orelse('not found').val() 

Returns what you are looking for if it exists, or "not found" otherwise.

The general strategy in soupy is to wrap data that interests you in thin shell classes. A simple example of such a shell:

 class Scalar(object): def __init__(self, val): self._val = val def __getattr__(self, key): return Scalar(getattr(self._val, key, None)) def __call__(self, *args, **kwargs): return Scalar(self._val(*args, **kwargs)) def __str__(self): return 'Scalar(%s)' % self._val s = Scalar('hi there') s.upper() # Scalar('HI THERE') sabcd # Scalar(None) 

If you want to be interested in this, the mathematical property that allows you to safely hang things forever is closure (i.e., methods return instances of the same type). Many BeautifulSoup methods do not have this property, which is a dry address.

+2
source

Source: https://habr.com/ru/post/984759/


All Articles