Print () kullanarak bir sınıfın örnekleri nasıl yazdırılır?


538

Python'daki ipleri öğreniyorum. Sınıf nesnesini işlevini Foobarkullanarak yazdırmaya çalıştığımda print()şöyle bir çıktı alıyorum:

<__main__.Foobar instance at 0x7ff2a18c>

Bir sınıfın ve nesnelerinin yazdırma davranışını (veya dize temsilini ) ayarlayabilmemin bir yolu var mı ? Örneğin , bir sınıf nesnesini çağırdığımda , veri üyelerini belirli bir biçimde yazdırmak istiyorum. Python'da bunu nasıl başarabilirim?print()

C ++ sınıflarına aşina iseniz, yukarıdaki sınıf için ostreambir friend ostream& operator << (ostream&, const Foobar&)yöntem ekleyerek standart için elde edilebilir .

Yanıtlar:


628
>>> class Test:
...     def __repr__(self):
...         return "Test()"
...     def __str__(self):
...         return "member of Test"
... 
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test

__str__Yöntemi yazdırmak ne olur, ve __repr__yöntem kullanmak ne olur repr()fonksiyonunu (veya etkileşimli istemi ile baktığınızda). Bu en Pythonic yöntem değilse, özür dilerim, çünkü hala öğreniyorum - ama işe yarıyor.

Herhangi bir __str__yöntem verilmezse, Python __repr__bunun yerine sonucu yazdıracaktır . Tanımlar __str__ancak tanımlamazsanız __repr__, Python yukarıda gördüğünüz şeyi kullanır __repr__, ancak yine __str__de yazdırma için kullanır .


11
Str yerine kullanabileceğiniz bir unicode yöntemi de vardır ; bir dize değil, bir unicode nesnesi döndürmesi gerektiğini unutmayın (ancak bir dize döndürürseniz, unicode'a dönüştürme işlemi yine de yapılacaktır ...)
kender

@kender - Bunu bilmiyordum, ama geçmişe bakıldığında Python 2.x'in Unicode kullanımının bozulması göz önüne alındığında mükemmel bir anlam ifade ediyor.
Chris Lutz

11
Bence bu cevap diğerine bir bağlantı olmadan tamamlanamaz !
tnotstar

Beni kurtardı! Ancak, __repr __ (self) yöntemini yeniden uyguladıktan sonra, yazdırma kullanıcıları yanlış yönlendirir. Bu konudaki en iyi uygulamalardan haberdar mısınız?
Viet

10
Java programcılarına: __str __ (self) python dünyasının toString () gibidir
Janac Meena

134

Chris Lutz'un belirttiği gibi , bu __repr__sınıfınızdaki yöntemle tanımlanır .

Aşağıdakilerin dokümantasyonundan repr():

Birçok tür için bu işlev, iletildiğinde aynı değere sahip bir nesneyi verecek bir dize döndürme girişiminde bulunur eval(), aksi takdirde temsil, nesnenin türünün adını ek bilgilerle birlikte içeren açılı parantez içine alınmış bir dizedir genellikle nesnenin adı ve adresini içerir. Bir sınıf, bir __repr__()yöntem tanımlayarak bu işlevin örnekleri için ne döndürdüğünü denetleyebilir .

Aşağıdaki sınıf Testi verildi:

class Test:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __repr__(self):
        return "<Test a:%s b:%s>" % (self.a, self.b)

    def __str__(self):
        return "From str method of Test: a is %s, b is %s" % (self.a, self.b)

.. Python kabuğunda aşağıdaki şekilde hareket edecektir:

>>> t = Test(123, 456)
>>> t
<Test a:123 b:456>
>>> print repr(t)
<Test a:123 b:456>
>>> print(t)
From str method of Test: a is 123, b is 456
>>> print(str(t))
From str method of Test: a is 123, b is 456

__str__Tanımlanmış bir yöntem yoksa , print(t)(veya print(str(t))) __repr__bunun yerine sonucu kullanır

Herhangi bir __repr__yöntem tanımlanmamışsa, varsayılan değer kullanılır.

def __repr__(self):
    return "<%s instance at %s>" % (self.__class__.__name__, id(self))

+1 ancak sınıf kodlarınız __str__, etkileşimli kabuğun sonuçlarından farklıdır. : P
Chris Lutz

1
Hata, ayıp .. REPL çıkışını manuel olarak değiştirmek asla iyi bitmez. Muhtemelen gönderilerimi doctest etmeliyim: P
dbr

1
%Dize biçimlendirme gelen, kaldırılmış değildir docs.python.org/whatsnew/2.6.html "% operatörü olan desteklenmiş ) yöntemini, biçimini (biçimlendirme daha güçlü bir dize tarafından"
dbr

4
Dbr: Bu doğru. "Python 3.0 Yenilikler" doc de "format () yöntemi [...] Bu plan sonunda dize biçimlendirme için tek API yapmak ve Python 3.1% operatörünü kullanımdan kaldırmak olduğunu unutmayın."
Ashwin Nanjappa

1
Pitty, %çok uygun.
Janusz Lenar

52

Belirli bir biçimlendirme olmadan herhangi bir sınıfa uygulanabilen genel bir yol aşağıdaki gibi yapılabilir:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

Ve sonra,

elem = Element('my_name', 'some_symbol', 3)
print(elem)

üretir

__main__.Element: {'symbol': 'some_symbol', 'name': 'my_name', 'number': 3}

23

@Keith gibi bir durumdaysanız deneyebilirsiniz:

print a.__dict__

İyi bir stil olarak değerlendireceğim şeylere karşı çıkıyor ama sadece hata ayıklamaya çalışıyorsanız, istediğiniz şeyi yapmalısınız.


Dikte anahtarının değerlerinde nesne olup olmadığını nasıl anlarsınız?
pranaygoyal02

1
@HadoopEvangelist Bu nesneleri de özyinelemeli olarak nasıl yazdıracağınızı mı yoksa sadece nesne olup olmadığını nasıl belirlediğinizi mi soruyorsunuz?
John

13

Sadece iki sentimi @ dbr'nin cevabına eklemek için, bu cümleyi alıntıladığı resmi belgelerden nasıl uygulayacağına dair bir örnek:

"[...] eval (), [...] 'a iletildiğinde aynı değere sahip bir nesne verecek bir dize döndürmek için

Bu sınıf tanımı göz önüne alındığında:

class Test(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __str__(self):
        return "An instance of class Test with state: a=%s b=%s" % (self._a, self._b)

    def __repr__(self):
        return 'Test("%s","%s")' % (self._a, self._b)

TestSınıf örneğini serileştirmek artık çok kolay :

x = Test('hello', 'world')
print 'Human readable: ', str(x)
print 'Object representation: ', repr(x)
print

y = eval(repr(x))
print 'Human readable: ', str(y)
print 'Object representation: ', repr(y)
print

Yani, kodun son parçasını çalıştırdığımızda şunları elde ederiz:

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Human readable:  An instance of class Test with state: a=hello b=world
Object representation:  Test("hello","world")

Ama, son yorumda söylediğim gibi: daha fazla bilgi sadece burada !


12

Kullanmanız gerekiyor __repr__. Bu standart bir işlevdir __init__. Örneğin:

class Foobar():
    """This will create Foobar type object."""

    def __init__(self):
        print "Foobar object is created."

    def __repr__(self):
        return "Type what do you want to see here."

a = Foobar()

print a

2
repr ve str farklı semantiklere sahiptir: repr , aynı nesneyi (yeniden) yaratacak Python kaynağı olmalıdır; bu, koddaki repr oluşumudur; str , nesnenin oldukça kullanıcı tarafından dizilenmesi olmalıdır.
Eric Towers

12

@ User394430 tarafından yanıtın daha güzel bir sürümü

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number

    def __str__(self):
        return  str(self.__class__) + '\n'+ '\n'.join(('{} = {}'.format(item, self.__dict__[item]) for item in self.__dict__))

elem = Element('my_name', 'some_symbol', 3)
print(elem)

İsimlerin ve değerlerin görsel olarak güzel bir listesini üretir.

<class '__main__.Element'>
name = my_name
symbol = some_symbol
number = 3

Hatta daha meraklı bir versiyon (teşekkürler Ruud) öğeleri sıralar:

def __str__(self):
    return  str(self.__class__) + '\n' + '\n'.join((str(item) + ' = ' + str(self.__dict__[item]) for item in sorted(self.__dict__)))

8

Python 3 için:

Belirli biçim önemli değilse (örn. Hata ayıklama için) aşağıdaki Yazdırılabilir sınıftan miras alın. Her nesne için kod yazmaya gerek yoktur.

Bu cevaptan ilham alındı

class Printable:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)

# Example Usage
class MyClass(Printable):
    pass

my_obj = MyClass()
my_obj.msg = "Hello"
my_obj.number = "46"
print(my_obj)

1

Zaten bu konuda çok cevap var ama hiçbiri özellikle bana yardımcı olmadı, kendim çalışmak zorunda kaldım, bu yüzden umarım bu biraz daha bilgilendirici.

Sınıfınızın sonunda parantez bulunduğundan emin olmanız gerekir, örneğin:

print(class())

İşte üzerinde çalıştığım bir projeden kod örneği:

class Element:
    def __init__(self, name, symbol, number):
        self.name = name
        self.symbol = symbol
        self.number = number
    def __str__(self):
        return "{}: {}\nAtomic Number: {}\n".format(self.name, self.symbol, self.number

class Hydrogen(Element):
    def __init__(self):
        super().__init__(name = "Hydrogen", symbol = "H", number = "1")

Hidrojen sınıfımı yazdırmak için aşağıdakileri kullandım:

print(Hydrogen())

Hidrojen sonunda parantez olmadan bunun işe yaramayacağını lütfen unutmayın. Onlar gereklidir.

Umarım bu yardımcı olur, başka sorunuz varsa bana bildirin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.