On 8/9/2015 9:02 PM, Eric V. Smith wrote: > On 8/9/2015 8:24 PM, Peter Ludemann wrote: >> What if logging understood lambda? (By testing for types.FunctionType). >> This is outside PEP 498, but there might be some recommendations on how >> "lazy" evaluation should be done and understood by some functions. >> >> e.g.: >> log.info <http://log.info>(lambda: f'{foo} just did a {bar} thing') >> >> It's not pretty, but it's not too verbose. As far as I can tell, PEP 498 >> would work with this because it implicitly supports closures — that is, >> it's defined as equivalent to >> log.info <http://log.info>(lambda: ''.join([foo.__format__(), ' just did >> a ', bar.__format__(), ' thing'])) >> > > That basically works: > class Foo: > def __init__(self, name): > self.name = name > > def __format__(self, fmt): > print(f'__format__: {self.name}') > return f'{self.name}' > > > class Logger: > # accumulate log messages until flush is called > def __init__(self): > self.values = [] > > def log(self, value): > self.values.append(value) > > def flush(self): > for value in self.values: > if callable(value): > value = value() > print(f'log: {value}') > > logger = Logger() > > f1 = Foo('one') > f2 = Foo('two') > print('before log calls') > logger.log('first log message') > logger.log(lambda:f'f: {f1} {f2}') > logger.log('last log message') > print('after log calls') > f1 = Foo('three') > logger.flush() > > > produces: > > before log calls > after log calls > log: first log message > __format__: three > __format__: two > log: f: three two > log: last log message > > > But note that when the lambdas are called, f1 is bound to Foo('three'), > so that's what's printed. I don't think that's what the logging module > would normally do, since it wouldn't see the rebinding. > > I guess you'd have to change logging to do something special if it had a > single argument which is a callable, or add new interface to it. > > And of course you'd have to live with the ugliness of lambdas in the > logging calls. > > So, I can't say I'm a huge fan of the approach. But writing examples > using f-strings is way more fun that using %-formatting or str.format!
Here's a better example that shows the closure. Same output as above: class Foo: def __init__(self, name): self.name = name def __format__(self, fmt): print(f'__format__: {self.name}') return f'{self.name}' class Logger: # accumulate log messages until flush is called def __init__(self): self.values = [] def log(self, value): self.values.append(value) def flush(self): for value in self.values: if callable(value): value = value() print(f'log: {value}') def do_something(logger): f1 = Foo('one') f2 = Foo('two') print('before log calls') logger.log('first log message') logger.log(lambda:f'f: {f1} {f2}') logger.log('last log message') print('after log calls') f1 = Foo('three') logger = Logger() do_something(logger) logger.flush() _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com