杨东明 发表于 2021-7-12 22:01:27

请问为啥wrapper后面不是要求两个参数吗?test1一个a也行的啊。??

>>> def log(func):
    def wrapper(*args,**kwargs):
      print('log开始 ...')
      ret = func(*args,**kwargs)
      print('log结束 ...')
      return ret
    return wrapper


@log
def test1(a):
    print('test1 ..', a)
    return a


def test2():
    print('test2 ..')

print(test1.__name__)
print(test2.__name__)

阿奇_o 发表于 2021-7-12 22:01:28

本帖最后由 阿奇_o 于 2021-7-13 16:08 编辑

杨东明 发表于 2021-7-13 09:45
类不是class定义吗?wrapper不是函数吗。。还有就是第10行的@修饰符下的test1()函数是不是被修饰函数, ...

准确来说,__name__ 应该不仅仅包括 “模块名”或“类名”,而是 包括
definition.__name__
The name of the class, function, method, descriptor, or generator instance.
导入时,才是指“模块名”,
__name__
The __name__ attribute must be set to the fully-qualified name of the module. This name is used to uniquely identify the module in the import system.

换言之,可以看做是 当前命名空间的唯一标识符(独一无二的一个名字),使用 globals() 查看,就明白了:
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'log': <function log at 0x0000026960AD19D8>, 'test1': <function log.<locals>.wrapper at 0x0000026960ADF9D8>, 'test2': <function test2 at 0x0000026960B27DC8>}

可以看到,被@log修饰的test1函数,指向的是 (作为) 函数log的一个局部变量 : log.<locals>.wrapper
当你用 print(test1.__name__) 时,它 只打印了 wrapper 这个变量名。
(又或者说,这里print其实是 调用用了 log.<locals>.wrapper.__str__() 其返回的字符串,刚好是 wrapper。 若是自定义的类,你其实可以重写__str__,就可以返回任何字符串...)
>>> class MyClass():
        def __str__(self):
                return '我叫MyClass'
>>> obj = MyClass()
>>> print(obj)
我叫MyClass
>>> obj.__str__()
'我叫MyClass'
>>>




OK,应该可以明白了。。

至于 参数个数的问题,是python的语法特性,* 代表若干个(0-N个参数,皆可)具体Twilight大佬已经解释了。

杨东明 发表于 2021-7-12 22:04:08

还有就是19行test1.__name__不是只会返回函数名test1或者‘main’吗?没懂为啥会返回wrapper

运行结果:wrapper
               test2

杨东明 发表于 2021-7-12 22:06:27

第10行的@修饰符下的test1()函数是不是被修饰函数,它是以func = test1(a)的方式传进log函数里面吗?但是没懂为啥wrapper两个参数,test1一个参数也可以??

Twilight6 发表于 2021-7-13 01:49:22

杨东明 发表于 2021-7-12 22:04
还有就是19行test1.__name__不是只会返回函数名test1或者‘main’吗?没懂为啥会返回wrapper

运行结果: ...


请问为啥wrapper后面不是要求两个参数吗?

*参数 是表示收集参数成元组,可以 0 ~ 理论无穷多

**参数 是表示收集参数成字典,也可以 0 ~ 理论无穷多

关键字参数必须位于位置参数之后,这里 字典收集参数必须为关键字参数

__name__不是只会返回函数名test1或者‘main’吗?

__name__ 是返回此时运行对象的程序模块名,而每一个 Python 的类都能当成模块,所以这里返回 wrapper

杨东明 发表于 2021-7-13 09:45:32

Twilight6 发表于 2021-7-13 01:49
*参数 是表示收集参数成元组,可以 0 ~ 理论无穷多

**参数 是表示收集参数成字典,也可以 0 ~...

类不是class定义吗?wrapper不是函数吗。。还有就是第10行的@修饰符下的test1()函数是不是被修饰函数,它是以func = test1(a)的方式传进log函数里面吗?

杨东明 发表于 2021-7-13 16:27:06

阿奇_o 发表于 2021-7-13 15:52
准确来说,__name__ 应该不仅仅包括 “模块名”或“类名”,而是 包括




谢谢,懂了些了,我想再问问你写的代码,第7行有时候我看定义类后面不需要加(),我想问问这儿加与不加有什么含义吗??还有就是第11行我敲了一下代码,为啥我的运行打印的是   <__main__.B object at 0x00000139ADFD1D88>
代码是:
>>> class B():
        def str(self):
                return '你好'

       
>>> b = B()
>>> print (b)
<__main__.B object at 0x00000139ADFD1D88>

杨东明 发表于 2021-7-13 16:32:44

阿奇_o 发表于 2021-7-13 15:52
准确来说,__name__ 应该不仅仅包括 “模块名”或“类名”,而是 包括




再问问print (b)后打印的 __main__.B object at 0x00000139ADFD1D88 ,这个__main__是啥意思{:9_240:}

阿奇_o 发表于 2021-7-13 18:55:23

本帖最后由 阿奇_o 于 2021-7-13 19:04 编辑

杨东明 发表于 2021-7-13 16:27
谢谢,懂了些了,我想再问问你写的代码,第7行有时候我看定义类后面不需要加(),我想问问这儿加与不加 ...

是 __str__(self) ,不是 str(self),这些双下划线的 都是Python的 “特殊方法”。 有特殊的用处,涉及数据结构、对象运算等等。
至于 类名后 加不加 (),都可以,若要指定继承父类,就要加(默认其实都继承object类,不用写)。。。 这些都是小语法、小细节,不重要。。。
又因为 __str__这特殊方法在object这总父类里肯定有,你没有在子类里 正确重写 __str__ , 那它就往上找,调用了 总父类的object的 __str__ , 其默认 返回啥,就是啥。。。

嗯,看来你,面向对象部分,也不太了解,可以先去 菜鸟教程或w3cshool等网站,先看看简单的OOP例子。


杨东明 发表于 2021-7-13 20:51:15

阿奇_o 发表于 2021-7-13 15:52
准确来说,__name__ 应该不仅仅包括 “模块名”或“类名”,而是 包括




谢谢{:9_231:}

杨东明 发表于 2021-7-13 20:51:54

Twilight6 发表于 2021-7-13 01:49
*参数 是表示收集参数成元组,可以 0 ~ 理论无穷多

**参数 是表示收集参数成字典,也可以 0 ~...

谢谢{:9_231:}
页: [1]
查看完整版本: 请问为啥wrapper后面不是要求两个参数吗?test1一个a也行的啊。??