Python学习笔记3

装饰器

函数装饰器

装饰器就是在不改动原有函数的前提下,动态修改函数的功能,然后返回一个新函数。

py 复制代码
def my_decorator(func): 
    def wrapper(): 
        print("在原函数之前执行") 
        func() 
        print("在原函数之后执行") 
        return wrapper 

@my_decorator 
def say_hello(): 
    print("Hello!") 
    
say_hello() # 在原函数之前执行 # Hello! # 在原函数之后执行

装饰器函数也可以接收到原函数的参数:

py 复制代码
def my_decorator(func): 
    def wrapper(*args, **kwargs): 
        print(f"在原函数之前执行, {args}") 
        func(*args, **kwargs) 
        print(f"在原函数之后执行, {args}") 
        return wrapper 
        
@my_decorator 
def greet(name): 
    print(f"Hello, {name}!") greet("Alice") 
    
# 在原函数之前执行, ('Alice',) # Hello, Alice! # 在原函数之后执行, ('Alice',)

注意:装饰器不是继承!装饰器是在不改变原始函数的前提下,通过对原始函数的包装来扩展它的功能。而继承是子类在扩展父类。

类装饰器

类装饰器的效果和函数装饰器大致相同,接收一个类作为参数,返回一个修改过的新类。

py 复制代码
def log_class(cls): 
"""类装饰器,在调用方法前后打印日志""" 
    class Wrapper: 
        def __init__(self, *args, **kwargs): 
            self.wrapped = cls(*args, **kwargs) 
            # 实例化原始类 
            def __getattr__(self, name): 
                """拦截未定义的属性访问,转发给原始类""" 
                return getattr(self.wrapped, name) 
                
            def display(self): 
                print(f"调用 {cls.__name__}.display() 前") 
                self.wrapped.display() 
                print(f"调用 {cls.__name__}.display() 后") 
                return Wrapper 
                # 返回包装后的类 
                
@log_class 
class MyClass: 
    def display(self): 
        print("这是 MyClass 的 display 方法") 
        obj = MyClass() 
        obj.display() 
        
# 调用 MyClass.display() 前 
# 这是 MyClass 的 display 方法 
# 调用 MyClass.display() 后

内置装饰器

  1. @staticmethod: 将方法定义为静态方法,不需要实例化类即可调用。
  2. @classmethod: 将方法定义为类方法,第一个参数是类本身(通常命名为 cls)。
  3. @property: 将方法转换为属性,使其可以像属性一样访问。
py 复制代码
class MyClass: 
    @staticmethod 
    def static_method(): 
        print("这是一个静态方法!") 
        
    @classmethod 
    def class_method(cls): 
        print(f"这是一个类方法 {cls.__name__}.") 
        
    @property 
    def name(self): 
        return self._name 
            
    @name.setter 
    def name(self, value): 
        self._name = value 
            
# 使用 
MyClass.static_method() 
MyClass.class_method() 
obj = MyClass() 
obj.name = "Alice" 
print(obj.name)

多个装饰器堆叠

装饰器可以通过堆叠的方式对函数进行无限扩展,多个装饰器存在的时候会按照从上到下的顺序依次应用。

py 复制代码
def decorator1(func): 
    def wrapper(): 
        print("Decorator 1") 
        func() 
        return wrapper 
        
def decorator2(func): 
    def wrapper(): 
        print("Decorator 2") 
        func() 
        return wrapper 
        
@decorator1 
@decorator2 
def say_hello(): 
    print("Hello!") 
    
say_hello()

引用

Python使用 import 关键字对其他 py 模块进行引用。

py 复制代码
import supper supper.test('123')

注意:在Python中无论文件声明了多少次 import ,只要是相同的文件,则当前文件只会被导入一次!

Python 导入文件的查找路径为:当前脚本目录 → PYTHONPATH → 标准库 → 第三方包(site-packages)

这种导入方案带来的一个问题是项目中不能存在相同名称的模块,否则会存在冲突

所以永远不要给模块/代码库起相同的名字

部分引用

Python 支持部分导入的模式,使用 form...import 的形式。

py 复制代码
from fibo import fib, fib2 fib(500) # 1 1 2 3 5 8 13 21 34 55 89 144 233 377

还可以通过使用 as 关键字对导入的函数重命名。

py 复制代码
import numpy as np # 将 numpy 模块别名设置为 np from math import sqrt as square_root # 将 sqrt 函数别名设置为 square_root

全量引用

可以使用 * 字符将所有的函数导入进来。

py 复制代码
from modname import *

注意:不建议使用此方式,可能会导致命名冲突。

__name__ 属性

使用引入的方式开发某些功能时,我们可能希望在原始函数中执行某个功能,在引入的代码中屏蔽这个功能。

可以使用 __name__ 属性,当在原始函数中执行的时候 __name__ == '__main__'

py 复制代码
if __name__ == '__main__': 
    print('程序自身在运行') 
else: 
    print('我来自另一模块')

注意__name__ 属性始终存在,在原始函数中叫 __main__,在引入函数中为模块名。

dir方法

Python 存在一个内置方法 dir() ,可以获取到模块内定义的所有名称。

py 复制代码
import fibo, sys 
dir(fibo) 
# ['__name__', 'fib', 'fib2'] 

dir(sys) 
""" 
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions'] 
"""
相关推荐
luod1 小时前
Python包
python
Mr Lee_1 小时前
Smali 文件生成dex装箱算法整合
开发语言·python·算法
电饭叔1 小时前
《python语言程序设计》2018版--第8章14题利用字符串输入作为一个信用卡号之一(Luhn算法解释)
android·java·python
小女孩真可爱1 小时前
大模型学习记录(八)---------RAG评估
linux·人工智能·python
刘晓倩1 小时前
Python3的Sequence
开发语言·python
ZhengEnCi1 小时前
一次多线程同步问题的排查:从 thread_count 到 thread.join() 的踩坑之旅
python·网络协议·tcp/ip
ULTRA??2 小时前
ROS Action 完整示例(AI辅助):客户端发目标 + 服务器接参数(lambda 替代 boost::bind)
c++·python
free-elcmacom2 小时前
用Python玩转GAN:让AI学会“造假”的艺术
人工智能·python·机器学习
计算机毕设匠心工作室2 小时前
【python大数据毕设实战】全国健康老龄化数据分析系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习
后端·python