Bisakah saya mencetak nama instance suatu kelas?

Saya mencoba mencetak nama instance suatu kelas. Dalam contoh ini, ini adalah pengatur waktu yang mencetak berapa lama berbagai bagian kode saya yang tumpang tindih berjalan:

class timerstart:
    def __init__(self):
        # Sets some variables with system time

    def stop(self):
        # Calculates current total time
        print(*instance name*, 'total time is ...')

Jadi ketika saya menyebutnya dalam kode saya akan terlihat seperti:

allcode=timerstart()
  # some code
    subcode=timerstart()
      # some code
    subcode.stop()
  # some code
allcode.stop()

Yang akan menghasilkan:

subcode total time...
allcode total time...

Saya tahu saya dapat menginisialisasi fungsi dengan namanya: allcode=timerstart(name='allcode') yang mengganggu.

Saya juga mengalami masalah dengan penelusuran balik menggunakan: inspect.currentframe().f_back.f_locals.items()

Apakah ada cara untuk mencetak nama instance, seperti print(self.selfname) atau apalah?


person Audelia    schedule 04.12.2019    source sumber
comment
Pertimbangkan pertanyaan ini: Mendapatkan nama variabel sebagai string   -  person Ṃųỻịgǻňạcểơửṩ    schedule 04.12.2019
comment
Tidak, instance tidak memiliki nama. Variabel adalah pemetaan satu arah, karena beberapa variabel dapat merujuk ke objek yang sama, tetapi objek tersebut tidak mengetahui apa pun tentang nama yang merujuk ke objek tersebut.   -  person chepner    schedule 04.12.2019
comment
Anda mungkin ingin menjadikan timerstart sebagai pengelola konteks, sehingga Anda dapat menulis with timerstart("allcode"): .... Badan pernyataan with akan membatasi blok yang akan diberi waktu, bukan diakhiri dengan panggilan eksplisit ke stop.   -  person chepner    schedule 04.12.2019
comment
Apakah ini menjawab pertanyaan Anda? python mendapatkan nama variabel argumen dalam suatu fungsi   -  person Fred Larson    schedule 04.12.2019


Jawaban (3)


Jadikan timerstart sebagai pengelola konteks. Maka Anda tidak memerlukan referensi ke objek timer sama sekali.

import time


class timer:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        self.start = time.time()

    def __exit__(self, *args):
        print(f'{self.name} total time {time.time() - self.start}')

Kemudian Anda akan menulis kode Anda menggunakan pernyataan with:

with timer("allcode"):
    # some code
    with timer("subcode"):
        # some sub-block
    # some more code

Anda mungkin dapat mendefinisikan manajer menggunakan contextlib.contextmanager daripada mendefinisikan metode __enter__ dan __exit__ secara eksplisit pada suatu kelas.

import contextlib


@contextlib.contextmanager
def timer(name):
    start = time.time()
    yield
    print(f'{name} total time {time.time() - start}')
person chepner    schedule 04.12.2019

Jawaban singkatnya adalah: Tidak selalu berhasil. Nama variabel Python adalah pemetaan satu arah ke objek tersebut. Instance yang sama bisa mempunyai beberapa nama, artinya beberapa variabel mengacu pada instance yang sama. Contoh sederhananya adalah:

obj1 = [1,2,3]
obj2 = obj1
# Demonstration that the object is now obj2 and obj1 at the same time
obj2[0] = 0
obj1 = [0,2,3]

Di sini, objek yang dibuat oleh obj1 juga menggunakan nama obj2. Mencetak atau mendapatkan nama instance kelas ini sekarang menjadi ambigu.

Cara terbaik untuk mendapatkan nama objek allcode dan subcode adalah dengan menetapkan bidang nama, dan membuat instance seperti yang Anda lakukan sebelumnya, atau memodifikasi konstruktor sehingga Anda harus memberi nama padanya.

person Ṃųỻịgǻňạcểơửṩ    schedule 04.12.2019
comment
Saya hanya tertarik pada nama inisialisasinya. Jika nama variabel lain ditetapkan ke objek tersebut nanti, masuk akal jika variabel tersebut tetap ditelusuri kembali ke nama asli yang membuat instance objek tersebut. Hal ini tidak akan menimbulkan ambiguitas pada nama dan harus mudah dilacak, seperti menetapkan nama bidang - person Audelia; 05.12.2019
comment
Python tidak 'mengingat' nama variabel pada saat inisialisasi. Cara terbaik adalah dengan menetapkan nama field wajib ke variabel. - person Ṃųỻịgǻňạcểơửṩ; 05.12.2019

Saya telah membungkusnya ke dalam sebuah paket: https://github.com/pwwang/python-varname

Anda dapat dengan mudah melakukannya dengan paket:

import time
from varname import varname

class timerstart:
    def __init__(self):
        self.name = varname()
        self.start = time.time()
        # Sets some variables with system time

    def stop(self):
        # Calculates current total time
        print(self.name, 'total time is ', time.time() - self.start)

allcode=timerstart()

# some code
time.sleep(1)

subcode=timerstart()

# some code
time.sleep(1)

subcode.stop()

# some code
time.sleep(1)

allcode.stop()

Ini mencetak:

subcode total time is  1.0007166862487793
allcode total time is  3.0030770301818848
person Panwen Wang    schedule 09.07.2020