Python: __qualname__ of function with decorator

Asked
Active3 hr before
Viewed126 times

7 Answers

pythonqualnamedecoratorfunction
90%

name of module in which this class was defined,name of module in which this method was defined,name of module in which this function was defined,name with which this class was defined

Example_snippet/controller/utility/_python.js/ def gen(): yield @types.co. . .
def gen():
   yield
@types.coroutine
def gen_coro():
   yield

assert not isawaitable(gen())
assert isawaitable(gen_coro())
load more v
88%

This comes down to the fact that qualname uses the line number attribute of the code attribute of the function, and functools,wraps doesn't change the code object

Example_snippet/controller/utility/_python.js/ import functools from qualname. . .
import functools
from qualname
import qualname

def decorator(f):
   @functools.wraps(f)
def wrapper( * args, ** kwargs):
   return f( * args, ** kwargs)
return wrapper

@decorator
def h():
   pass

print(qualname(h))
print(h.__qualname__)
load more v
72%

functools is a standard Python module for higher-order functions (functions that act on or return other functions), wraps() is a decorator that is applied to the wrapper function of a decorator

Example_snippet/controller/utility/_python.js/ wrapper A wrapper function wra. . .
wrapper
A wrapper
function
wrapper
A wrapper
function
load more v
65%

Example_snippet/controller/utility/_python.js/ def my_function(): pass c. . .
def my_function():
   pass

class MyClass(object):
   def method(self):
   pass

print(my_function.__name__) # gives "my_function"
print(MyClass.method.__name__) # gives "method"

print(my_function.__qualname__) # gives "my_function"
print(MyClass.method.__qualname__) # gives "MyClass.method"
load more v
75%

Administration User List Committer List , Summaries Issues with patch Easy issues Stats

Example_snippet/controller/utility/_python.js/ Python 3 introduced __qualname. . .
Python 3 introduced __qualname__. This attribute exists on class types and also instances of certain class types, such as functions. For example:

def f(): pass

print(f.__name__)
print(f.__qualname__)

class Class: pass

print(Class.__name__)
print(Class.__qualname__)

yields:

f
f
Class
Class

An instance of a class however does not have __name__ or __qualname__ attributes. With:

c = Class()

print(c.__name__)
print(c.__qualname__)

yielding:

Traceback (most recent call last):
File "qualnametest.py", line 13, in <module>
   print(c.__name__)
   AttributeError: 'Class' object has no attribute '__name__'

   Traceback (most recent call last):
   File "qualnametest.py", line 14, in <module>
      print(c.__qualname__)
      AttributeError: 'Class' object has no attribute '__qualname__'

      For a class, it is possible to override the __name__ attribute using a property.

      class Class:
      @property
      def __name__(self):
      return 'override'

      c = Class()

      print(c.__name__)

      With the result being:

      override

      This is useful in writing object proxies or function wrappers for decorators as rather than having to copy the __name__ attribute into the wrapper, the lookup can be deferred until when it is required.

      The same though cannot be done for __qualname__. With:

      class Class:
      @property
      def __qualname__(self):
      return 'override'

      yielding an error when the class definition is being processed:

      Traceback (most recent call last):
      File "qualnametest.py", line 16, in <module>
         class Class:
         TypeError: type __qualname__ must be a str, not property

         This means the same trick cannot be used in object proxies and function wrappers and instead __qualname__ must be copied and assigned explicitly as a string attribute in the __init__() function of the object proxy or function wrapper.

         I can sort of understand a prohibition on __qualname__ being a string attribute in certain cases, especially if overriding it on a type or instance where __qualname__ attribute already exists, but I don't understand why a limitation would be imposed to prevent using a property as a means of generating the value for a class instance which doesn't otherwise have a __qualname__ attribute. There is no similar restriction for __name__.

         Unless there is a good specific reason for this behaviour, the ability to override it with a property in cases where the __qualname__ attribute didn't already exist, would be handy for proxies and wrappers.
load more v
40%

I'm using a Decorator (class) in an Instance method of another class, like this:,Now, when I print out self,sayHello

Example_snippet/controller/utility/_python.js/ class decorator_with_arguments. . .
class decorator_with_arguments(object):

   def __init__(self, arg1 = 0, arg2 = 0, arg3 = 0):
   self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3

def __call__(self, f):
   print("Inside __call__()")
def wrapped_f( * args):
   print(f.__qualname__)
f( * args)
return wrapped_f

class Lol:
   @decorator_with_arguments("hello")
def sayHello(self, a1, a2, a3, a4):
   print(self.sayHello.__qualname__)
load more v
22%

You can simply copy the __qualname__ attribute across to your wrapped_f wrapper function; it is this function that is returned when the decorator is applied, after all,,The @wraps(f) decorator there copies the relevant attributes from f onto wrapped_f, including __qualname__:,You could use the @functools

Example_snippet/controller/utility/_qualname.js/ from functools import wraps c. . .
from functools
import wraps

class decorator_with_arguments(object):
   def __init__(self, arg1 = 0, arg2 = 0, arg3 = 0):
   self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3

def __call__(self, f):
   print("Inside __call__()")
@wraps(f)
def wrapped_f( * args):
   print(f.__qualname__)
f( * args)
return wrapped_f
load more v