Python: defining new functions on the fly using c

I want to convert the following code:

... urls = [many urls] links = [] funcs = [] for url in urls: func = getFunc(url, links) funcs.append(func) ... def getFunc(url, links): def func(): page = open(url) link = searchForLink(page) links.append(link) return func 

in a much more convenient code:

 urls = [many urls] links = [] funcs = [] for url in urls: <STATEMENT>(funcs): page = open(url) link = searchForLink(page) links.append(link) 

I was hoping to do this with the with statement. As I commented below, I was hoping to achieve:

 def __enter__(): def func(): ..code in the for loop.. def __exit__(): funcs.append(func) 

Of course, this does not work.

List enumerations are not suitable for cases when the searchForLink action is not only one function, but also many functions. This would turn into extremely unreadable code. For example, even this would be problematic with a list:

 for url in urls: page = open(url) link1 = searchForLink(page) link2 = searchForLink(page) actionOnLink(link1) actionOnLink(link2) .... many more of these actions... links.append(link1) 
+4
source share
7 answers

A bit unconventional, but you can have a decorator, register func and bind any loop variables as default arguments:

 urls = [many urls] links = [] funcs = [] for url in urls: @funcs.append def func(url=url): page = open(url) link = searchForLink(page) links.append(link) 
+4
source

It makes no sense to use with here. Use list comprehension instead:

 funcs = [getFunc(url, links) for url in urls] 
+6
source

Lose the line <STATEMENT>(funcs):

Edit:

I mean: why do you do this? Why define a new function for each page? Why not just do it?

 urls = [many urls] links = [] for url in urls: page = open(url) link = searchForLink(page) links.append(link) 
+2
source

There are only two ways to create functions: def and lambda . Lambdas are designed for tiny functions, so they may not be very suitable for your case. However, if you really want this, you can enclose two lambdas inside each other:

 urls = [many urls] links = [] funcs = [(lambda x: lambda: links.append(searchForLink(open(x))))(u) for u in urls] 

A bit too lispish for my taste.

+2
source

You should not use the ā€œcā€ for this (although given that it is Python, you could almost certainly use some fancy side effect and dynamism of Python).

The goal of "c" in Python is, as described in the docs , to "wrap block execution using specific methods using the context manager, which allows you to use a normal attempt ... except ... finally, usage patterns that should be encapsulated for easy reuse "

I think you are confusing Python with " Javascript / VisualBasic " with ", which may be cosmetically similar, but which is not actually related.

+1
source

Good old itertools .

 from itertools import imap links.extend(imap(searchForLink, imap(open, urls))) 

Although you may prefer functional .

 from functional import * funcs = [partial(compose(compose(links.append, searchForLink), open), url) for url in urls] for func in funcs: func() 

I don't think it's worth creating a class for with use: it works more to create __enter__ and __exit__ than just writing a helper function.

+1
source

You might be better off using generators to achieve computed computed calculations.

 def MakeLinks(urls): for url in urls: page = open(url) link = searchForLink(page) yield link links = MakeLinks(urls) 

If you need links:

 for link in links: print link 

URLs will be browsed during this cycle, and not all at once (which is similar to what you are avoiding).

+1
source

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


All Articles