1

I am new python here. I have a question.The code just like this:

def get(path):
    '''
    Define decorator @get('/path')
    '''
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            return func(*args, **kw)
        wrapper.__method__ = 'GET'
        wrapper.__route__ = path
        return wrapper
    return decorator

This is a decorator,I don't understand

"

  wrapper.__method__ = 'GET'
     wrapper.__route__ = path

"__xxx__" generally used to define special methods and properties, why the code define function's property use the style? Isn’t this not advocating? And can dynamically add attributes to functions as well as dynamically adding attributes to a class? Thx so much~

U13-Forward
  • 69,221
  • 14
  • 89
  • 114
Lee
  • 11
  • 3
  • 5
    If you're new to Python, you're looking at entirely the wrong kind of Python code. – Sneftel May 25 '18 at 06:08
  • Thank you. I just do not understand why the code add function's property like this style. Double underscore beginning and ending generally used for special variables?Just like __name__ or __init__ – Lee May 25 '18 at 06:16
  • 1
    Yes, a function is a first class object with attributes you can set and modify somewhat freely. At the same time, making custom dunder attributes is specifically frowned upon by the language, so whoever wrote this code was counting on no conflicting changes being introduced to Python itself. Don't do stuff like that. But generally adding attributes to functions is perfectly fine. – Mad Physicist May 25 '18 at 06:17
  • @lee. Double underscore (dunder) attributes are all explicitly reserved by the language. – Mad Physicist May 25 '18 at 06:18
  • Got it. Thank you much.You just helped me a lot~ @Mad Physicist – Lee May 25 '18 at 06:24
  • Put it another way, `method`, `_method`, `method_`, `_method_` are all totally fine. `__method__` is functionally fine with the currently available versions if Python, but a really bad idea. `__method` is not fine at all because it won't survive name mentioning m mangling. – Mad Physicist May 25 '18 at 06:25
  • @lee. Would you like for me to daft an actual answer you can accept? – Mad Physicist May 25 '18 at 06:25
  • @Mad Physicist. what did you mean? I am new here. This is the first time I use stackoverflow. Sorry – Lee May 25 '18 at 06:31
  • I think @lee meant "draft" (write), not "daft". – cdarke May 25 '18 at 06:33
  • @cdarke. You think right :) – Mad Physicist May 25 '18 at 06:37
  • haha, I misunderstood your words,Sorry.@Mad Physicist. a function is a first class object with attributes you can set and modify somewhat freely. At the same time, making custom dunder attributes is specifically frowned upon by the language, so whoever wrote this code was counting on no conflicting changes being introduced to Python itself. method, _method, method_, _method_ are all totally fine. __method__ is functionally fine with the currently available versions if Python, but a really bad idea. – Lee May 25 '18 at 06:40
  • @Lee. I will elaborate momentarily with actual references to the manual. – Mad Physicist May 25 '18 at 06:43
  • Related: https://stackoverflow.com/q/338101/2988730 – Mad Physicist May 25 '18 at 07:17

1 Answers1

0

There are really two questions here: one about assigning arbitrary attributes to functions, and another about assigning special/double underscore (dunder)/magic attributes.

Assigning attributes to functions is perfectly fine. According to the docs:

Functions are first-class objects.

This does not automatically mean that you can assign attributes to them, but it is a good indication. Functions objects have a writable __dict__1, which is what makes setting attributes possible. This is an intentional and frequently-used feature. The following SO question elaborates on the subject: Python function attributes - uses and abuses.

The issue with the code shown is with the improper use of dunder attributes. Basically, using dunder attributes for anything other than officially documented use is a bad idea:

Any use of __*__ names, in any context, that does not follow explicitly documented use, is subject to breakage without warning.

There are two particular problems here. The main issue is that adding undocumented dunder attributes can potentially conflict with the normal callable attributes setup by functools.wraps (listed in the Data Model1). The secondary issue is that adding dunder attributes may add undesirable behaviors to the object in certain cirsumstances, since they are used as flags by the interpreter.

There are a number of alternative naming conventions to be aware of, some of which would have been more appropriate than a dunder method:

  • For example, renaming __method__ to _method would make it "private by convention", since Python does not really recognize the concept of privacy as such.
  • A modified version of _method would be _method_. This is a convention that is used by the builtin enum package exactly to avoid clobbering reserved names.
  • Using a plain name is of course always fine: method instead of __method__.
  • A naming scheme that would not work would be __method. This triggers name mangling by the interpreter, so the name would be inaccessible as such by the caller. This would be a much worse idea than just using dunder names, which would cause no real problems for any interpreter that I am aware of at the moment.

TL;DR

Assigning attributes to a function is quite useful and fully supported. Assigning to dunder attributes, however, is questionable at best.


1 Scroll down to "Callable Types"

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264