15.11.17 12:53, Ivan Levkivskyi пише: > On 15 November 2017 at 08:43, Serhiy Storchaka <storchaka at gmail.com > <mailto:storchaka at gmail.com>> wrote: > > It is worth to mention that using name as a module global will > bypass __getattr__. And this is intentional, otherwise calling > __getattr__ for builtins will harm a performance. > > > Good point! And please document idiomatic way of using a module global with triggering __getattr__. For example if you want to use a lazy loaded submodule. sys.modules[__name__].foobar or from . import foobar The difference between them that the latter sets the module attribute, thus __getattr__ will be called only once. > Backwards compatibility and impact on performance > ================================================= > > > What is affect on pydoc, word completion, inspect, pkgutil, unittest? > > > This is rather gray area. I am not sure that we need to update them in > any way, just the people who use __getattr__ should be aware that > some tools might not yet expect it.. I will add a note to the PEP about > this. This problem is not new, since it was possible to replace a module with a module subclass with overridden __getattr__ and __dir__ before, but now this problem can occur more often. > I would create more standard helpers (for deprecation, for lazy > importing). This feature is helpful not by itself, but because it > will be used for implementing new features. Using __getattr__ > directly will need to write a boilerplate code. Maybe when > implementing these helper you will discover that this PEP needs some > additions. > > > > But in which module these helpers should live? Good question. lazy_import() could be added in importlib (or importlib.util?). The helper that just adds deprecation on importing a name, could be added in importlib too. But I think that it would be better if the deprecated() helper will also create a wrapper that raises a deprecation warning on the use of deprecated function. It could be added in the warnings or functools modules. I would add also a more general lazy_initialized(). It is something like cached module property. Executes the specified code on first use, and cache the result as a module attribute. In all these cases the final __getattr__ method should be automatically constructed from different chunks. At the end it could call a user supplied __getattr__. Or maybe the module method __getattr__ should look first at special registry before calling the instance attribute __getattr__()? def ModuleType.__getattr__(self, name): if name in self.__properties__: call self.__properties__[name]() elif '__getattr__' in self.__dict__: call self.__dict__['__getattr__'](name) else: raise AttributeError I'm wondering if the __set_name__ mechanism can be extended to modules. What if call the __set_name__() method for all items in a module dict after finishing importing the module?
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4