On Nov 30, 2019, at 08:02, Ricky Teachey <[email protected]> wrote:
>
>
> It sounds like many would agree that renaming some things could have many
> benefits, but the cost seems to be higher than I imagined.
>
> What if an easier way could be created to manage renaming that avoided many
> of these problems?
>
> Perhaps aliases of objects could be something worth baking into the language
> itself. I don't mean having multiple names pointing to the same object as we
> can do today, but something new entirely.
Are you suggesting we allow this so users/projects can add their own aliases
into the stdlib, or so that the stdlib can grow a whole mess of aliases?
> THE FOLLOWING IS PROBABLY A CRACKPOT IDEA, hear it out of you are in the mood
> to humor me on this Saturday morning.
>
> What if the __dict__ for modules and classes could be something like a
> ChainMap, with multiple internal lookup mappings. The first level (by which I
> mean, the first mapping consulted) would be the same as exists today, but the
> second would contain a weak value dictionary with aliases pointing to objects
> so that when you do json.load_str, it returns json.loads object just like it
> would if you had added the alias in the way you would today. But the dict is
> weak value so that if an object is garbage collected, its alias entries are
> removed.
So if you monkeypatch json.loads, its last reference might go away, in which
case json.load_str becomes a dead weakref and can no longer be used? What’s the
benefit of that? Wouldn’t it be better to make load_str alias loads by name, so
if an existing module monkeypatches loads, it automatically changes load_str as
well?
> So the second mapping would be a so called "alias dictionary".
>
> How could this be done to overcome some of the same objections raised?
>
> First, regarding discoverability:
>
> dir() would work identically to as it does today, but you could give an
> argument to also provide aliases, something like:
>
> >>> dir(json, alias=True)
> ['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__',
> '__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
> '__name__', '__package__', '__path__', '__spec__', '__version__',
> '_default_decoder', '_default_encoder', 'codecs', 'decoder',
> 'detect_encoding', 'dump', 'dumps [dump_str]', 'encoder', 'load', 'loads
> [load_str]', 'scanner']
>
> Note that when you tell dir() that alias=True, additional aliases for objects
> are added to the output in the form of a string-ified list.
But not the same as actually stringifying a list, which gives you the reprs of
its members.
Also, this means tools now have to understand how to parse this language; you
can’t just do `for name in dir(spam): something(name)`, you have to do
something like:
for name in dir(spam, alias=True):
if match := re.match(r'(\w+) \[(.*?)\])', name):
something(match.groups(1))
for alias in groups(2).split(', '):
something(alias)
else:
something(name)
Of course you could write a helper function to do the heavy lifting, but it’s
still going to be nontrivial.
And all existing tools that rely on dir (e.g., to autocomplete in a REPL or
IDE, or to build a proxy object that exposes the same names) aren’t going to
see aliases until they’re changed to do this.
> Also change the default object repr so that it says something like:
>
> >>> json.loads
> <function loads (alias: load_str) at 0x.... >
How does it even know that? Does it have to look at its module and name, then
look at the module’s alias dict?
> Most importantly, it seems like it would be preferred for * importing
> everything from a module to import only the first level dictionary and not
> all the aliases.
Doesn’t that defeat the purpose of aliases? If you don’t have them at the REPL
when you * import, you’re going to learn the “unintuitive” name that is
available, instead of learning the “intuitive” one.
Also, won’t it be at least annoying, if not confusing, if the help, dir, and
repr mention the alias but you can’t use it?
> Additionally, you can still add or monkeypatch new objects into a namespace
> (they would go into the first level dictionary, therefore overriding any
> aliases in the second level). Beyond that, since I'm talking about something
> new baked into the language, the code writing tools would be updated to know
> about aliases and provide useful auto complete functionality that makes it
> clear this is an alias.
How are you imagining that working? When you autocomplete in the standard REPL
or ipython or bpython or PyCharm or PyDev, what will they do to indicate that
it’s an alias?
> For convenient addition of aliases and discovering them for a specific
> member:
>
> There are likely all sorts of ways you could do this. Perhaps a dunder alias
> combined with an alias decorator could be added (probably in functools? not
> top level)?
>
> You could add an alias like:
>
> @functools.alias("load_str")
> def loads(...): ...
>
> assert loads.__alias__ == ["load_str"]
Is this dunder a @property that looks at the module’s alias namespace? Or is it
actually a copy of the same information? If so, how are they kept in sync? (Or
is that just a “consenting adults” thing—if you only add aliases with the
decorator the two are in sync, but if you don’t, you have to do it right
manually or you’ll confuse people.)
> class MyClass:
> @functools.alias("prof")
> def process_file(self, ...): ...
>
> assert MyClass.process_file.__alias__ == ["prof"]
So classes also have an alias dict? And presumably their dir also changes?
And unbound methods obviously have aliases (because they’re just functions),
but what about bound methods (and classmethods and custom method-y decorators)?
For example, if `mine = MyClass()`, does `mine.process_file.__alias__` also
work? How? Do method objects have a @property for the dunder that delegates to
the underlying `__func__`? If not, I don’t think this would be very useful.
You’d also need to rewrite what __getatrribute__ does to look at aliases on the
class and base classes (and on the object, or is that not allowed?), which
would break most existing custom __getattribute__ methods.
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/YFFSZNV637SVIC5FKVSDHKVTXV7LNZST/
Code of Conduct: http://python.org/psf/codeofconduct/