代码学习(二)

1. @contextmanager上下文管理

参考:https://www.cnblogs.com/yeer-xuan/p/13493902.html

用它装饰的函数默认可以使用with进行上下文管理,这个被装饰的函数必须有一个yield用来划分enter和exit。举个例子:

from contextlib import contextmanager

class File():
    def read_file(self):
        print("read file")

@contextmanager
def openfile():
    print("open")
    yield File()
    print("close")

with openfile() as f:
    f.read_file()

# >>> open
# >>> read file
# >>> close

可以看到,在上下文管理器中调用被修饰的函数openfile,先执行openfile中yield之前的代码,yield的内容作为f的值,然后执行with里面的语句,最后执行openfile中yield之后的内容。

2. collections.abc.Mapping

这个可以用来判断某个对象是不是字典。

from collections.abc import Mapping

# 判断value是不是一个字典可以写成下面的形式
print(isinstance(value, Mapping)) # True for dict

3. __call__的用法

__call__可以让类的实例当作函数一样被调用使用。

参考:Python中的__init__()和__call__()函数___init__ 和__call__-CSDN博客

4.UUID生成唯一识别码 

参考:python 中uuid1,uuid3,uuid4与uuid5的区别-CSDN博客

使用uuid库可以生成唯一识别码

import uuid

print(str(uuid.uuid4()))

# >>> 941beb66-e4e5-46ea-a07f-80dc762a02d5

5.globals()返回文件的内在属性

globals()返回文件内部属性

print(globals())

# {'__name__': '__main__', '__doc__': None, '__package__': None, 
# '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002EC27176CD0>, '__spec__': None, 
# '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
# '__file__': 'e:\\projects\\vscode\\2024spring\\detectron2\\__init__.py', '__cached__': None}

也可以通过globals进行函数的调用 

def a():
    print("1111")

globals()["a"]()

# >>> 1111

6.方法和函数的区别

函数是独立的,方法是有依赖的,依赖于类等,可以用.去访问。


import inspect


class A:
    def k(self):
        pass
    @classmethod
    def q(cls,):
        pass
    @staticmethod
    def v():
        pass
    def m():
        pass
print(inspect.ismethod(A().k)) # True
print(inspect.ismethod(A().q)) # True
print(inspect.ismethod(A().v)) # False
print(inspect.isfunction(A().v)) # True
print(inspect.ismethod(A().m)) # True

7. python内置关键字any

any用于判断给定的可迭代对象(例如列表、元组、集合等)中是否至少有一个元素为真。如果至少有一个元素为真,则返回 True,否则返回 False

8. inspect.signature

用来获取函数的参数,并可以进行判断,包含下面几种类型的入口参数:

import inspect

# 只能靠位置传递
# POSITIONAL_ONLY
def k(a, b, /, c=1):
    pass
signature = inspect.signature(k)
for param in signature.parameters.values():
    print(param.kind)
# >>> POSITIONAL_ONLY
# >>> POSITIONAL_ONLY
# >>> POSITIONAL_OR_KEYWORD

# 既可以是位置参数,又可以是关键字参数,最常见的
# POSITIONAL_OR_KEYWORD
def k(a, b, c=1):
    pass
signature = inspect.signature(k)
for param in signature.parameters.values():
    print(param.kind)   
# >>> POSITIONAL_OR_KEYWORD
# >>> POSITIONAL_OR_KEYWORD
# >>> POSITIONAL_OR_KEYWORD

# 可变的位置参数
# VAR_POSITIONAL
def k(*args):
    pass
signature = inspect.signature(k)
for param in signature.parameters.values():
    print(param.kind)  
# >>> VAR_POSITIONAL

# 只能靠关键字输入
# KEYWORD_ONLY
def k(a, *, b=1):
    pass
signature = inspect.signature(k)
for param in signature.parameters.values():
    print(param.kind) 
# >>> POSITIONAL_OR_KEYWORD
# >>> KEYWORD_ONLY
    
# 可变的关键字参数
# VAR_KEYWORD
def k(**kwargs):
    pass
signature = inspect.signature(k)
for param in signature.parameters.values():
    print(param.kind) 
# >>> VAR_KEYWORD

9. @property

参考:python @property的介绍与使用 - 知乎

这个装饰器用来装饰类内的方法,把方法当作一个属性来访问。

class A:
    @property
    def b(self):
        return 1

print(A().b) # 得实例化后才能访问
# >>> 1

10.dataclass数据类

参考:Python中的数据类dataclass详解_python dataclass-CSDN博客

dataclass是一个装饰器,默认实现了类的__init__,__rper__,__eq__等方法。

from dataclasses import dataclass, field
from typing import List

@dataclass
class Player:
    name: str
    number: int
    money: int

@dataclass
class Team:
    name: str
    player: List[Player]

jam = Player("Jam", 13, 100000)
paul = Player("Paul", 18, 100000)
team = Team("Mavericks", [jam, paul])
print(jam)
print(team)

# >>>Player(name='Jam', number=13, money=100000)
# >>>Team(name='Mavericks', player=[Player(name='Jam', number=13, money=100000), Player(name='Paul', number=18, money=100000)])


这里发现了dataclasses中有个函数叫field,它是干什么的呢?

参考:Python中的数据类dataclass详解_python dataclass-CSDN博客

简单来讲,就是在dataclass类中,List等使用可变默认参数, 导致多个实例公用一个数据的类型不能直接指定默认值。

这个时候指定默认值就得用field了。

from typing import List, TypeVar
from dataclasses import dataclass, field

@dataclass
class a:
    x : List[int] = field(default_factory=lambda: [1,2,3])

a()

# >>> a(x=[1, 2, 3])

11.defaultdict

参考:python中defaultdict用法详解 - 简书

defaultdict的用处在于当字典的key不存在时,索引它并不会报错,而是会返回一个默认值。

from collections import defaultdict

a = defaultdict(int)
a['a'] = 1
print(a['a'])
print(a['b'])
# >>>1
# >>>0

12. python函数的入口参数中*是什么意思

有下面这种函数定义方式:

def func1(
        a,
        b,
        *,
        c=1,
        d=2,
):
    pass

疑惑这里的*是干什么的?这里的*表示,在你传参的时候,位置参数,也就是这里的a和b,没有默认值的,只能有前面俩,后面的c和d是关键字参数,必须显示的制定出来。给一个例子就可以很清楚的看出来了:

def func1(
        a,
        b,
        *,
        c=1,
        d=2,
):
    pass

func1(1,2,3,4)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[1], line 10
      1 def func1(
      2         a,
      3         b,
   (...)
      6         d=2,
      7 ):
      8     pass
---> 10 func1(1,2,3,4)

TypeError: func1() takes 2 positional arguments but 4 were given

然而:

def func1(
        a,
        b,
        # *,
        c=1,
        d=2,
):
    pass

func1(1,2,3,4)

注释掉*后,完全没问题。

def func1(
        a,
        b,
        *,
        c=1,
        d=2,
):
    pass

func1(1,2,c=3,d=4)

显示指定也没问题。

总结,就是*之后的内容必须显示的指定出来。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值