Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Improve alias signatures#11939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
NelleV merged 1 commit intomatplotlib:masterfromtimhoffm:alias-signature
Aug 26, 2018
Merged

Conversation

timhoffm
Copy link
Member

PR Summary

Until now, all alias methods had the signature*args, **kwargs. This is not very helpful as it's unclear which arguments are expected (well, usually none for getters and one for setters, but the alias method does not tell).

This PR uses inspect to copy the signatures of the original functions to the alias.

Example setter

before:
grafik

now:
grafik

Example getter

before:
grafik

now:
grafik

@timhoffmtimhoffm added this to thev3.1 milestoneAug 26, 2018
@@ -1914,20 +1914,28 @@ class so far, an alias named ``get_alias`` will be defined; the same will
if cls is None: # Return the actual class decorator.
return functools.partial(_define_aliases, alias_d)

def make_alias(name): # Enforce a closure over *name*.
def method(self, *args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Just add a@functools.wraps(getattr(cls, name)) decorator here? inspect.signature will then get the signature from the wrappee. Note that you can even play with theassigned kwarg to functools.wraps if you don't want to update the name...

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks for the hint. That would work too.

The getattr-alias is a bit slower than my explictly coded lambda (67ns vs. 26ns). I mean, it's not much in absolute values, but the aliases might be used a lot by users. Do we want the added speedup or should we stay with the slightly simpler but slower getattr implementiation.

Copy link
Contributor

@anntzeranntzerAug 26, 2018
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

No strong opinion there; though eval() whill likely have a small extra startup cost as well?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

There are 60 properties. The package import time does not measureably change between the two approaches (200.8 +/- 6.0ms vs. 201.0 +/- 6.0ms).

Probably both approaches are fast enough in startup as well as runtime use to not make a difference. I will go back to decorating the original function to keep it simpler. If runtime performance is really super-critical, users should just use the methods functions, not the aliases.

return method
def make_alias(method):
import inspect
args = str(inspect.signature(method))[1:-1] # remove parentheses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

str(inspect.signature(functools.partial(method, None))) will bind the first argument for you and remove it from the signature more easily than the text wrangling below :) (plus it even works if someone decides to not call the first argument "self", hehe... for example it could just be a wrapper function itself being*args, **kwargs)

@timhoffm
Copy link
MemberAuthor

For future reference, this was the first approach, which was discarded in favor of simply decorating the alias with@functools.wraps(getattr(cls, name)).

    def make_alias(method):        import inspect        args = str(inspect.signature(method))[1:-1]  # remove parentheses        if args[:6] == 'self, ':            call_args = args[6:]        elif args == 'self':            call_args = ''        else:            raise RuntimeError('Unexpected signature: %s' % args)        alias_method = eval('lambda {}: self.{}({})'.format(            args, method.__name__, call_args))        alias_method.__doc__ = "Alias for `{}`.".format(method.__name__)        return alias_method    for prop, aliases in alias_d.items():        exists = False        for prefix in ["get_", "set_"]:            if prefix + prop in vars(cls):                exists = True                for alias in aliases:                    method = make_alias(getattr(cls, prefix + prop))                    method.__name__ = prefix + alias                    setattr(cls, prefix + alias, method)        if not exists:            raise ValueError(                "Neither getter nor setter exists for {!r}".format(prop))

Copy link
Member

@NelleVNelleV left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This looks good to me.

(although about this whole functionality:
There should be one-- and preferably only one --obvious way to do it. 😭 )

@NelleVNelleV merged commitd5433f6 intomatplotlib:masterAug 26, 2018
@NelleV
Copy link
Member

Thanks@timhoffm

@timhoffmtimhoffm deleted the alias-signature branchAugust 26, 2018 20:00
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@NelleVNelleVNelleV approved these changes

@anntzeranntzeranntzer approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
v3.1.0
Development

Successfully merging this pull request may close these issues.

3 participants
@timhoffm@NelleV@anntzer

[8]ページ先頭

©2009-2025 Movatter.jp