รับชื่อของตัวแปรเป็นสตริง


173

หัวข้อนี้อธิบายวิธีรับชื่อฟังก์ชั่นเป็นสตริงใน Python: วิธีรับชื่อฟังก์ชั่นเป็นสตริง?

ฉันจะทำเช่นเดียวกันสำหรับตัวแปรได้อย่างไร ตรงข้ามกับฟังก์ชั่นตัวแปร Python ไม่มี__name__คุณสมบัติ

กล่าวอีกนัยหนึ่งถ้าฉันมีตัวแปรเช่น:

foo = dict()
foo['bar'] = 2

ฉันกำลังมองหาฟังก์ชั่น / คุณสมบัติเช่นretrieve_name()เพื่อสร้าง DataFrame ใน Pandas จากรายการนี้โดยที่ชื่อคอลัมน์จะได้รับจากชื่อของพจนานุกรมจริง:

# List of dictionaries for my DataFrame
list_of_dicts = [n_jobs, users, queues, priorities]
columns = [retrieve_name(d) for d in list_of_dicts] 

คำตอบ:


19

เมื่อใช้python-varnameแพ็คเกจคุณสามารถดึงชื่อตัวแปรได้อย่างง่ายดาย

https://github.com/pwwang/python-varname

ในกรณีของคุณคุณสามารถทำได้:

from varname import Wrapper

foo = Wrapper(dict())

# foo.name == 'foo'
# foo.value == {}
foo.value['bar'] = 2

หรือคุณสามารถลองเรียกชื่อตัวแปรโดยตรง:

from varname import nameof

foo = dict()

fooname = nameof(foo)
# fooname == 'foo'

ฉันเป็นผู้เขียนของแพ็คเกจนี้ โปรดแจ้งให้เราทราบหากคุณมีคำถามใด ๆ หรือคุณสามารถส่งปัญหาเกี่ยวกับ Github


2
ตกลงในที่สุดก็รับมัน! ติดตั้งโดยใช้ต่อไปนี้pip3 install python-varname==0.1.5; นำเข้าโดยใช้from varname import nameof
enter_display_name_here

อย่างใดฟังก์ชั่นไม่ทำงานในลูป: test = {} print(varname.nameof(test)) for i in [0]: print(varname.nameof(test))การพิมพ์ครั้งแรกให้testพิมพ์ในลูปยกVarnameRetrievingError: Callee's node cannot be detected.
Tillus

1
@Tillus แก้ไขที่v0.2.0
Panwen Wang

107

วัตถุเดียวใน Python ที่มีชื่อบัญญัติคือโมดูลฟังก์ชั่นและคลาสและแน่นอนไม่รับประกันว่าชื่อบัญญัตินี้มีความหมายใด ๆ ในเนมสเปซใด ๆ หลังจากมีการกำหนดฟังก์ชันหรือคลาสหรือโมดูลที่นำเข้า ชื่อเหล่านี้สามารถแก้ไขได้หลังจากที่วัตถุถูกสร้างขึ้นเพื่อให้พวกเขาอาจไม่น่าเชื่อถือโดยเฉพาะอย่างยิ่ง

สิ่งที่คุณต้องการจะทำคือไปไม่ได้โดยไม่ซ้ำเดินต้นไม้ของวัตถุชื่อ ; ชื่อคือการอ้างอิงทางเดียวกับวัตถุ วัตถุ Python ทั่วไปหรือความหลากหลายในสวนประกอบด้วยการอ้างอิงถึงชื่อของมัน ลองนึกภาพถ้าจำนวนเต็มทุก dict ทุกรายการทุก Boolean จำเป็นต้องมีรายการสตริงที่แสดงชื่อที่อ้างถึง! มันจะเป็นฝันร้ายของการนำไปใช้ซึ่งมีประโยชน์เพียงเล็กน้อยต่อโปรแกรมเมอร์


7
ขอบคุณ แต่ทำไมไพ ธ อนจึงทำสิ่งนี้เพื่อฟังก์ชั่น (เช่นวัตถุประเภท Python ประเภทหนึ่ง)
Amelio Vazquez-Reina

1
@kindall: อย่าลืมโมดูล: พวกเขามีชื่อที่ยอมรับเช่นกัน นอกจากนี้อย่าลืมว่า__name__สามารถแก้ไขได้ตลอดเวลาซึ่งหมายความว่าชื่อ "มาตรฐาน" อาจไม่ใช่ชื่อที่สามารถใช้ในการรับวัตถุ (เช่นเมื่อสร้างคลาสแบบไดนามิก)
nneonneo

8
คำสั่งของคุณ "มันก็เป็นไปไม่ได้" เป็นเท็จเช่น @ scohe001 แสดงให้เห็นว่า ฐานข้อมูลชื่อตัวแปรของ Python นั้นเหมือนกับฐานข้อมูลเชิงสัมพันธ์อื่น ๆ คุณสามารถค้นหาวัตถุที่เกี่ยวข้องใน "reverse" และส่งคืนชื่อที่พบครั้งแรกหรือชื่อตัวแปรที่ถูกต้องทั้งหมดสำหรับตัวแปรที่กำหนด
เตาแก๊ส

3
@hobs คุณถูกต้องทางเทคนิค ... เป็นประเภทที่ถูกต้องที่สุด อย่างไรก็ตามในทางปฏิบัติมีชื่อที่เป็นไปได้มากมายสำหรับวัตถุที่เป็นปัญหามากกว่าที่ควรจะได้รับ
kindall

1
@kindall ฉันคิดว่าคุณพูดถูกถ้าเกณฑ์ "คุ้มค่า" ของคุณคือ O (1) วนของ scohe001 จะเป็น O (N)
เตาแก๊ส

82

แม้ว่าค่าตัวแปรจะไม่ชี้กลับไปที่ชื่อคุณสามารถเข้าถึงรายการของตัวแปรที่กำหนดไว้และค่าของมันดังนั้นฉันจึงประหลาดใจที่มีเพียงคนเดียวที่แนะนำให้วนลูปผ่านที่นั่นเพื่อค้นหาชื่อ var ของคุณ

มีคนพูดถึงในคำตอบที่คุณอาจจะต้องเดินชาวบ้านกองและการตรวจสอบของทุกคนและ Globals ที่จะหาfooแต่ถ้าfooได้รับมอบหมายอยู่ในขอบเขตที่คุณโทรนี้retrieve_nameฟังก์ชั่นที่คุณสามารถใช้inspect's current frameเพื่อให้ได้ทั้งหมดของตัวแปรท้องถิ่นเหล่านั้น .

คำอธิบายของฉันอาจจะพูดเกินไปสักหน่อย (บางทีฉันควรจะใช้คำน้อยกว่า "foo") แต่นี่คือวิธีที่จะดูในรหัส ( โปรดทราบว่าหากมีตัวแปรมากกว่าหนึ่งตัวที่กำหนดให้กับค่าเดียวกันคุณจะ รับชื่อตัวแปรทั้งสอง ):

import inspect

x,y,z = 1,2,3

def retrieve_name(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    return [var_name for var_name, var_val in callers_local_vars if var_val is var]

print retrieve_name(y)

หากคุณเรียกใช้ฟังก์ชันนี้จากฟังก์ชั่นอื่นสิ่งที่ชอบ:

def foo(bar):
    return retrieve_name(bar)

foo(baz)

และคุณต้องการbazแทนที่จะbarคุณจะต้องย้อนกลับไปในขอบเขตต่อไป สามารถทำได้โดยการเพิ่มพิเศษ.f_backในการcaller_local_varsเริ่มต้น

ดูตัวอย่างได้ที่นี่: ideone


1
@theodox ฉันอย่างเห็นเช่นนี้อาจจะกระทำขึ้นด้วยimport hooks, ironpythonและjython
scohe001

5
สิ่งนี้ใช้ไม่ได้ ตัวแปร atomic ไม่มีชื่อเป็นแอตทริบิวต์ ดังนั้นถ้าคุณมีa, b = 2, 2, retrieve_name(a)และretrieve_name(b)ทั้งสองจะกลับมา['a', 'b']หรือ['b', 'a']
โทมัส

1
@tomas จริง ๆ แล้วนั่นคือรายละเอียดการใช้งานของการเพิ่มประสิทธิภาพของ cPython ซึ่งจำนวนเต็มต่ำกว่า 255 นั้นเป็น singletons ดังนั้นตัวแปรใด ๆ ที่กำหนดค่าเหล่านั้นจะกลับมามีประสิทธิภาพtrueสำหรับการisเปรียบเทียบ
Toote

1
มี mod ของสิ่งนี้เพื่อรับชื่อ var ที่ส่งผ่านหรือไม่ เช่นdef foo(bar): retrieve_name(bar)จะกลับแถบเสมอ แต่ถ้าคุณต้องการfoo(baz)กลับbaz) แทนที่จะเป็นbar?
SumNeuron

1
@SumNeuron คุณต้องการเพียงแค่มีการปรับเปลี่ยนเส้นที่กำหนดจะไปขอบเขตหนึ่งกลับต่อไปจึงจะได้รับการมองหาที่ขอบเขตของสิ่งที่จะเรียกcallers_local_vars fooเปลี่ยนบรรทัดเป็นinspect.currentframe().f_back.f_back.f_locals.items()(สังเกตเห็นส่วนเสริมf_back)
scohe001

37

ด้วย Python 3.8 หนึ่งสามารถใช้คุณสมบัติการดีบัก f-string:

>>> foo = dict()
>>> f'{foo=}'.split('=')[0]
'foo' 

เยี่ยมมาก! และถ้าคุณต้องการได้รับชื่อของทรัพย์สินแทนวัตถุที่คุณสามารถทำได้f'{foo=}'.split('=')[0].split('.')[-1]
Mickael V.

30

ใน python3 ฟังก์ชั่นนี้จะได้รับชื่อนอกสุดในสแต็ค:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

มันมีประโยชน์ทุกที่ในรหัส สำรวจสแต็กที่กลับด้านเพื่อค้นหาคู่แรก


งานที่ดี! แม้ว่าฉันจะลองretrieve_name(SomeClass.some_attribute)ใช้งานไม่ได้ คุณช่วยเพิ่มเติมได้ไหม?
Nam G VU

สิ่งนี้ต่อสู้กับตัวแปรบูลีน ฉันลงเอยด้วยstop_on_error
SumNeuron

26

ฉันไม่เชื่อว่าเป็นไปได้ ลองพิจารณาตัวอย่างต่อไปนี้:

>>> a = []
>>> b = a
>>> id(a)
140031712435664
>>> id(b)
140031712435664

aและbชี้ไปที่วัตถุเดียวกัน แต่วัตถุที่ไม่สามารถรู้ว่าสิ่งที่ตัวแปรชี้ไปที่มัน


2
แน่นอนความสัมพันธ์ที่สามารถทำสองทางโดยการขยายนับการอ้างอิง คำตอบนี้(และอื่น ๆ ) ให้การดำเนินการ
Shayaan

17
def name(**variables):
    return [x for x in variables]

มันใช้แบบนี้:

name(variable=variable)

12
สิ่งนี้จะไม่ส่งคืนชื่อของตัวแปรที่ต้องการ แต่เป็น "ตัวแปร" ยกตัวอย่างเช่น - ใช้name(variable=variable)ส่งออกจะ['variable']และการใช้name(variable=another_variable)จะไม่ส่งออกแต่['another_variable'] ['variable']
DalyaG

1
จริง ๆ แล้วมันทำงานได้ตามที่คาดไว้ คุณเพียงแค่ต้องแทนที่«ตัวแปร»ทั้งสองด้วยตัวแปรของคุณ มันจะส่งคืนรายการองค์ประกอบหนึ่งที่มีสตริงชื่อตัวแปรแรก ตัวอย่างเช่น: >>> a = [] >>> b = a >>> name(a=b) ['a'] >>> name(b=a) ['b']`
Alguem Meugla

8

นี่คือวิธีหนึ่ง ฉันจะไม่แนะนำสิ่งนี้สำหรับสิ่งสำคัญเพราะมันจะค่อนข้างบอบบาง แต่ก็สามารถทำได้

สร้างฟังก์ชันที่ใช้inspectโมดูลเพื่อค้นหาซอร์สโค้ดที่เรียกว่า จากนั้นคุณสามารถวิเคราะห์ซอร์สโค้ดเพื่อระบุชื่อตัวแปรที่คุณต้องการดึงข้อมูล ตัวอย่างเช่นต่อไปนี้เป็นฟังก์ชันautodictที่ใช้เรียกรายการตัวแปรและส่งคืนชื่อตัวแปรการแมปพจนานุกรมเป็นค่า เช่น:

x = 'foo'
y = 'bar'
d = autodict(x, y)
print d

จะให้:

{'x': 'foo', 'y': 'bar'}

การตรวจสอบซอร์สโค้ดเองนั้นดีกว่าการค้นหาผ่านlocals()หรือglobals()เพราะวิธีหลังไม่ได้บอกคุณว่าตัวแปรใดเป็นตัวที่คุณต้องการ

ไม่ว่าจะด้วยวิธีใดก็ตามนี่คือรหัส:

def autodict(*args):
    get_rid_of = ['autodict(', ',', ')', '\n']
    calling_code = inspect.getouterframes(inspect.currentframe())[1][4][0]
    calling_code = calling_code[calling_code.index('autodict'):]
    for garbage in get_rid_of:
        calling_code = calling_code.replace(garbage, '')
    var_names, var_values = calling_code.split(), args
    dyn_dict = {var_name: var_value for var_name, var_value in
                zip(var_names, var_values)}
    return dyn_dict

การกระทำที่เกิดขึ้นในบรรทัดด้วยซึ่งจะส่งกลับสตริงภายในรหัสที่เรียกว่าinspect.getouterframesautodict

ข้อเสียที่เห็นได้ชัดของเวทมนตร์ประเภทนี้คือมันทำให้สมมติฐานเกี่ยวกับวิธีการที่ซอร์สโค้ดมีโครงสร้าง และแน่นอนว่ามันจะไม่ทำงานเลยหากทำงานในล่าม


สวัสดีฉันมีคำถามสามข้อเท่านั้น: 1. ทำไม "1" 2. ทำไมต้อง "4" 3. ทำไมต้องเป็น "0" :)
Piotr Wasilewicz

7

ผมเขียนแพคเกจเวทมนตร์ที่จะทำชนิดของมหัศจรรย์นี้ทนทาน คุณสามารถเขียน:

from sorcery import dict_of

columns = dict_of(n_jobs, users, queues, priorities)

และส่งต่อไปยังตัวสร้างดาต้าเฟรม มันเทียบเท่ากับ:

columns = dict(n_jobs=n_jobs, users=users, queues=queues, priorities=priorities)

6
>>> locals()['foo']
{}
>>> globals()['foo']
{}

หากคุณต้องการเขียนฟังก์ชั่นของคุณเองก็สามารถทำได้เช่นนั้นคุณสามารถตรวจสอบตัวแปรที่กำหนดในท้องถิ่นแล้วตรวจสอบ globals หากไม่พบสิ่งใดคุณสามารถเปรียบเทียบกับ id () เพื่อดูว่าตัวแปรชี้ไปยังตำแหน่งเดียวกันในหน่วยความจำหรือไม่

หากตัวแปรของคุณอยู่ในคลาสคุณสามารถใช้ className dict .keys () หรือ vars (ตัวเอง) เพื่อดูว่าตัวแปรของคุณถูกกำหนดไว้หรือไม่


เกิดอะไรขึ้นถ้าชื่ออยู่ในกรอบผู้โทร? จากนั้นคุณจะต้องทำสิ่งที่โง่ ๆ เช่นเดินกองซ้อนและตรวจสอบทุกคนlocalsและglobals... และคุณเสี่ยงที่จะได้ชื่อผิดถ้าไม่มีจริง มันเป็นงานที่ไม่มีประโยชน์จริง ๆ
nneonneo

คำถามทั้งหมดนั้นโง่ ... แต่ถ้าเป็นสิ่งที่เขาต้องการจะทำก็เป็นไปได้ คุณสามารถใช้ Globals (). setdefault (var, <new object of type (var)) เพื่อสร้างบางอย่างเมื่อไม่มีสิ่งใดอยู่ ฉันไม่แน่ใจว่าสิ่งที่เขาต้องการ แต่อาจจะเรียนรู้ว่าตัวแปรถูกเก็บไว้ตามขอบเขตที่เขาสามารถหาสิ่งที่ดีกว่า
blakev

3

ใน Python คำหลักdefและclassคำหลักจะผูกชื่อเฉพาะกับวัตถุที่กำหนด (ฟังก์ชันหรือคลาส) ในทำนองเดียวกันโมดูลจะได้รับชื่อโดยอาศัยการถูกเรียกว่าบางสิ่งที่เฉพาะเจาะจงในระบบไฟล์ ในทั้งสามกรณีมีวิธีที่ชัดเจนในการกำหนดชื่อ "มาตรฐาน" ให้กับวัตถุที่เป็นปัญหา

อย่างไรก็ตามสำหรับชนิดอื่น ๆ ของวัตถุเช่นชื่อที่ยอมรับอาจเพียงแค่ได้อยู่ ตัวอย่างเช่นพิจารณาองค์ประกอบของรายการ องค์ประกอบในรายการไม่ได้ถูกตั้งชื่อเป็นเอกเทศและเป็นไปได้ทั้งหมดว่าวิธีเดียวที่จะอ้างถึงพวกเขาในโปรแกรมคือการใช้ดัชนีรายการในรายการที่มี หากมีการส่งรายการวัตถุดังกล่าวไปยังฟังก์ชันของคุณคุณอาจไม่สามารถกำหนดตัวระบุที่มีความหมายให้กับค่าได้

Python ไม่ได้บันทึกชื่อทางด้านซ้ายของการกำหนดลงในวัตถุที่กำหนดเพราะ:

  1. มันจะต้องค้นหาว่าชื่อใดเป็น "บัญญัติ" ท่ามกลางวัตถุที่ขัดแย้งกันหลายรายการ
  2. มันจะไม่สมเหตุสมผลกับวัตถุที่ไม่เคยถูกกำหนดให้กับชื่อตัวแปรที่ชัดเจน
  3. มันจะไม่มีประสิทธิภาพอย่างยิ่ง
  4. แท้จริงไม่มีภาษาอื่นใดในการดำรงอยู่ทำอย่างนั้น

ตัวอย่างเช่นฟังก์ชั่นที่กำหนดโดยใช้lambdaมักจะมี "ชื่อ" <lambda>มากกว่าชื่อฟังก์ชั่นที่เฉพาะเจาะจง

วิธีที่ดีที่สุดคือการขอให้ผู้โทรส่งผ่านรายชื่อ (ทางเลือก) หากการพิมพ์'...','...'ยุ่งยากเกินไปคุณสามารถยอมรับได้เช่นสตริงเดี่ยวที่มีรายการชื่อคั่นด้วยเครื่องหมายจุลภาค (เช่นเดียวกับnamedtuple)


3
>> my_var = 5
>> my_var_name = [ k for k,v in locals().items() if v == my_var][0]
>> my_var_name 
'my_var'

locals () - ส่งคืนพจนานุกรมที่มีตัวแปรท้องถิ่นของขอบเขตปัจจุบัน โดยการวนซ้ำในพจนานุกรมนี้เราสามารถตรวจสอบคีย์ที่มีค่าเท่ากับตัวแปรที่กำหนดได้เพียงการแยกคีย์จะทำให้เรามีข้อความของตัวแปรในรูปแบบสตริง

จาก (หลังจากเปลี่ยนไปเล็กน้อย) https://www.tutorialspoint.com/How-to-get-a-variable-name-as-a-string-in-Python


2

ฉันคิดว่ามันยากที่จะทำสิ่งนี้ใน Python เพราะความจริงง่ายๆที่คุณจะไม่มีทางรู้ชื่อของตัวแปรที่คุณใช้ ดังนั้นในตัวอย่างของเขาคุณสามารถทำได้:

แทน:

list_of_dicts = [n_jobs, users, queues, priorities]

dict_of_dicts = {"n_jobs" : n_jobs, "users" : users, "queues" : queues, "priorities" : priorities}

2

อีกวิธีหนึ่งในการทำสิ่งนี้ตามเนื้อหาของตัวแปรอินพุต:

(จะส่งคืนชื่อของตัวแปรแรกที่ตรงกับตัวแปรอินพุตไม่เช่นนั้นจะมีใครสามารถแก้ไขได้เพื่อรับชื่อตัวแปรทั้งหมดที่มีเนื้อหาเหมือนกับตัวแปรอินพุต)

def retrieve_name(x, Vars=vars()):
    for k in Vars:
        if type(x) == type(Vars[k]):
            if x is Vars[k]:
                return k
    return None

2

ฟังก์ชันนี้จะพิมพ์ชื่อตัวแปรด้วยค่าของมัน:

import inspect

def print_this(var):
    callers_local_vars = inspect.currentframe().f_back.f_locals.items()
    print(str([k for k, v in callers_local_vars if v is var][0])+': '+str(var))
***Input & Function call:***
my_var = 10

print_this(my_var)

***Output**:*
my_var: 10

2

ฉันมีวิธีการและในขณะที่ไม่มีประสิทธิภาพมากที่สุด ... มันใช้งานได้! (และมันไม่เกี่ยวข้องกับโมดูลแฟนซีใด ๆ )

โดยพื้นฐานแล้วมันจะเปรียบเทียบID ของตัวแปรของคุณกับglobals () ID ของตัวแปรแล้วส่งคืนชื่อของการจับคู่

def getVariableName(variable, globalVariables=globals().copy()):
    """ Get Variable Name as String by comparing its ID to globals() Variables' IDs

        args:
            variable(var): Variable to find name for (Obviously this variable has to exist)

        kwargs:
            globalVariables(dict): Copy of the globals() dict (Adding to Kwargs allows this function to work properly when imported from another .py)
    """
    for globalVariable in globalVariables:
        if id(variable) == id(globalVariables[globalVariable]): # If our Variable's ID matches this Global Variable's ID...
            return globalVariable # Return its name from the Globals() dict

1

หากเป้าหมายคือช่วยให้คุณติดตามตัวแปรของคุณคุณสามารถเขียนฟังก์ชั่นง่าย ๆ ที่ติดป้ายตัวแปรและคืนค่าและประเภทของมัน ตัวอย่างเช่นสมมติว่า i_f = 3.01 และคุณปัดเศษเป็นจำนวนเต็มที่เรียกว่า i_n เพื่อใช้ในรหัสแล้วต้องมีสตริง i_s ที่จะเข้าสู่รายงาน

def whatis(string, x):
    print(string+' value=',repr(x),type(x))
    return string+' value='+repr(x)+repr(type(x))
i_f=3.01
i_n=int(i_f)
i_s=str(i_n)
i_l=[i_f, i_n, i_s]
i_u=(i_f, i_n, i_s)

## make report that identifies all types
report='\n'+20*'#'+'\nThis is the report:\n'
report+= whatis('i_f ',i_f)+'\n'
report+=whatis('i_n ',i_n)+'\n'
report+=whatis('i_s ',i_s)+'\n'
report+=whatis('i_l ',i_l)+'\n'
report+=whatis('i_u ',i_u)+'\n'
print(report)

สิ่งนี้จะพิมพ์ไปที่หน้าต่างของการโทรแต่ละครั้งเพื่อจุดประสงค์ในการดีบั๊กและยังให้สตริงสำหรับรายงานที่เป็นลายลักษณ์อักษร ข้อเสียเพียงอย่างเดียวคือคุณต้องพิมพ์ตัวแปรสองครั้งในแต่ละครั้งที่คุณเรียกใช้ฟังก์ชัน

ฉันเป็นมือใหม่ใน Python และพบว่าวิธีนี้มีประโยชน์มากในการบันทึกความพยายามของฉันในขณะที่ฉันตั้งโปรแกรมและพยายามจัดการกับวัตถุทั้งหมดใน Python ข้อบกพร่องหนึ่งคือ whatis () ล้มเหลวหากเรียกใช้ฟังก์ชันที่อธิบายไว้ภายนอกโพรซีเดอร์ที่ใช้งาน ยกตัวอย่างเช่น int (i_f) เป็นฟังก์ชั่นการโทรที่ถูกต้องเพียงเพราะintฟังก์ชั่นเป็นที่รู้จักกันหลาม คุณสามารถเรียก whatis () โดยใช้ int (i_f ** 2) แต่ถ้าด้วยเหตุผลแปลก ๆ บางอย่างคุณเลือกที่จะกำหนดฟังก์ชั่นที่เรียกว่า int_squared มันจะต้องประกาศในขั้นตอนที่ใช้ whatis ()


1

บางทีนี่อาจเป็นประโยชน์:

def Retriever(bar):
    return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]

ฟังก์ชั่นจะต้องผ่านรายการ ID ของค่าจากขอบเขตทั่วโลก (เนมสเปซที่สามารถแก้ไขได้) ค้นหาดัชนีของ var ที่ต้องการ / จำเป็นหรือฟังก์ชั่นตาม ID ของมันแล้วส่งกลับชื่อจากรายการของชื่อโกลบอลตาม ในดัชนีที่ได้มา


1

วิธีการดังต่อไปนี้จะไม่ส่งคืนชื่อของตัวแปร แต่ใช้วิธีนี้คุณสามารถสร้างกรอบข้อมูลได้อย่างง่ายดายหากตัวแปรมีอยู่ในขอบเขตส่วนกลาง

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}

A = [0, 1]
B = [1, 2]
pd.DataFrame(G.A + G.B) # It will return a data frame with A and B columns

0

สำหรับค่าคงที่คุณสามารถใช้ enum ซึ่งรองรับการดึงชื่อ


0

ฉันพยายามรับชื่อจากคนในพื้นที่ แต่ไม่สามารถประมวลผล var ชอบ [1], b.val หลังจากนั้นฉันก็มีความคิดใหม่ --- รับชื่อ var จากโค้ดและฉันลองทำมันสำเร็จ! รหัสเช่นด้านล่าง:

#direct get from called function code
def retrieve_name_ex(var):
    stacks = inspect.stack()
    try:
        func = stacks[0].function
        code = stacks[1].code_context[0]
        s = code.index(func)
        s = code.index("(", s + len(func)) + 1
        e = code.index(")", s)
        return code[s:e].strip()
    except:
        return ""

0

คุณสามารถลองทำสิ่งต่อไปนี้เพื่อดึงชื่อของฟังก์ชั่นที่คุณกำหนดไว้ (ไม่ทำงานสำหรับฟังก์ชั่นในตัว):

import re
def retrieve_name(func):
    return re.match("<function\s+(\w+)\s+at.*", str(func)).group(1)

def foo(x):
    return x**2

print(retrieve_name(foo))
# foo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.