亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

動態響應解包賦值語句

動態響應解包賦值語句

LEATH 2022-01-05 10:46:01
在解包賦值語句中,被賦值的對象能否檢查它被賦值的變量數量?class MyObject:    def __iter__(self):        n = some_diabolical_hack()        print(f"yielding {n} vals")        return iter(["potato"]*n)就像是:>>> x, y = MyObject()yielding 2 vals>>> a, b, c = MyObject()yielding 3 vals在更一般的情況下,它可以內省target_list分配中使用的“形狀”嗎?>>> first, *blob, d[k], (x, y), L[3:7], obj.attr, last = MyObject()unpacking to <_ast.Tuple object at 0xcafef00d>示例潛在用例:MagicMock()當用于修補賦值語句右側的某個對象時,不需要預先配置固定迭代長度的改進。
查看完整描述

2 回答

?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

您可以使用回溯模塊:


import traceback


def diabolically_invoke_traceback():

    call = traceback.extract_stack()[-2]

    print call[3]

    unpackers = call[3].split('=')[0].split(',')

    print len (unpackers)

    return range(len(unpackers))


In [63]: a, b, c = diabolically_invoke_traceback()

a, b, c = diabolically_invoke_traceback()

3


In [64]: a

Out[64]: 0


In [65]: b

Out[65]: 1


In [66]: c

Out[66]: 2


查看完整回答
反對 回復 2022-01-05
?
慕勒3428872

TA貢獻1848條經驗 獲得超6個贊

也許您可以通過檢查調用幀的字節碼來做到這一點。如果我正確閱讀了字節碼指南,多重賦值由指令UNPACK_SEQUENCE或處理UNPACK_EX,具體取決于目標列表是否具有帶星號的名稱。這兩個指令都在其參數中提供了有關目標列表形狀的信息。


您可以編寫您的惡魔函數來爬升框架層次結構,直到找到調用框架,并檢查在FUNCTION_CALL代表賦值右側的之后發生的字節碼指令。(這是假設您調用的MyObject()是語句右側的唯一內容)。然后您可以從指令的參數中提取目標列表大小并返回它。


import inspect

import dis

import itertools


def diabolically_retrieve_target_list_size():

    #one f_back takes us to `get_diabolically_sized_list`'s frame. A second one takes us to the frame of the caller of `get_diabolically_sized_list`.

    frame = inspect.currentframe().f_back.f_back

    #explicitly delete frame when we're done with it to avoid reference cycles.

    try:

        #get the bytecode instruction that immediately follows the CALL_FUNCTION that is executing right now

        bytecode_idx = frame.f_lasti // 2

        unresolved_bytecodes = itertools.islice(dis.get_instructions(frame.f_code), bytecode_idx+1, bytecode_idx+3)

        next_bytecode = next(unresolved_bytecodes)

        if next_bytecode.opname == "UNPACK_SEQUENCE":   #simple multiple assignment, like `a,b,c = ...`

            return next_bytecode.arg

        elif next_bytecode.opname == "EXTENDED_ARG":    #multiple assignment with splat, like `a, *b, c = ...`

            next_bytecode = next(unresolved_bytecodes)

            if next_bytecode.opname != "UNPACK_EX":

                raise Exception(f"Expected UNPACK_EX after EXTENDED_ARG, got {next_bytecode.opname} instead")

            args_before_star = next_bytecode.arg % 256

            args_after_star = next_bytecode.arg >> 8

            return args_before_star + args_after_star

        elif next_bytecode.opname in ("STORE_FAST", "STORE_NAME"): #single assignment, like `a = ...`

            return 1

        else:

            raise Exception(f"Unrecognized bytecode: {frame.f_lasti} {next_bytecode.opname}")

    finally:

        del frame


def get_diabolically_sized_list():

    count = diabolically_retrieve_target_list_size()

    return list(range(count))


a,b,c = get_diabolically_sized_list()

print(a,b,c)

d,e,f,g,h,i = get_diabolically_sized_list()

print(d,e,f,g,h,i)

j, *k, l = get_diabolically_sized_list()

print(j,k,l)

x = get_diabolically_sized_list()

print(x)

結果:


0 1 2

0 1 2 3 4 5

0 [] 1

[0]


查看完整回答
反對 回復 2022-01-05
  • 2 回答
  • 0 關注
  • 232 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號