Lấy tên lớp của một thể hiện?


1437

Làm thế nào để tôi tìm ra một tên của lớp đã tạo ra một thể hiện của một đối tượng trong Python nếu hàm tôi đang thực hiện điều này là lớp cơ sở mà lớp của thể hiện đã được dẫn xuất?

Đã nghĩ rằng có lẽ mô-đun kiểm tra có thể đã giúp tôi ra khỏi đây, nhưng dường như nó không mang lại cho tôi những gì tôi muốn. Và thiếu phân tích __class__thành viên, tôi không biết làm thế nào để có được thông tin này.


Chính xác thì bạn đang 'phân tích cú pháp' từ biến lớp nào?
sykora

1
tên cấp cao nhất của lớp mà thể hiện thuộc về (không có tên mô-đun, v.v ...)
Dan

Tôi nghĩ điều ngược lại sẽ khó hơn (để có được lớp trong đó phương thức / hàm được định nghĩa).
Alexey

Câu trả lời:


1909

Bạn đã thử __name__thuộc tính của lớp chưa? tức là type(x).__name__sẽ cho bạn tên của lớp, mà tôi nghĩ là những gì bạn muốn.

>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'

Nếu bạn vẫn đang sử dụng Python 2, lưu ý rằng phương pháp trên hoạt động với các lớp kiểu mới (trong Python 3+ tất cả các lớp là các lớp "kiểu mới"). Mã của bạn có thể sử dụng một số lớp kiểu cũ. Các công việc sau đây cho cả hai:

x.__class__.__name__

41
Thật đơn giản Tự hỏi tại sao dir(x.__class__)không liệt kê nó?
cfi

43
Tại sao sử dụng __class__hơn typephương pháp? Giống như vậy : type(x).__name__. Không gọi hai thành viên gạch dưới trực tiếp làm nản lòng? Tôi không thể nhìn thấy một cách xung quanh bằng cách sử dụng __name__, mặc dù.
jpmc26

25
Bạn phải sử dụng __class__trực tiếp để tương thích với các lớp kiểu cũ, vì kiểu của chúng là vừa instance.
Quantum7

14
Điều này thường được sử dụng đủ để ghi nhật ký, mã orm và mã khung mà thực sự cần phải có một kiểu chữ dựng sẵn (x) ... yêu cầu người dùng nhìn vào "ruột" để có được một cái tên không quá tệ, IMO.
Erik Aronesty

5
@ErikAronesty,def typename(x): return type(x).__name__
sleblanc

391

Bạn có muốn tên của lớp là một chuỗi không?

instance.__class__.__name__

6
Hoặc ví dụ .__ class__ để lấy đối tượng lớp: D
Pencilcheck

8
Có an toàn để sử dụng hai thuộc tính gạch dưới?
Eduard Luca

5
@EduardLuca tại sao nó không an toàn? Các thuộc tính tích hợp sử dụng dấu gạch dưới để chúng không gây ra bất kỳ xung đột nào với mã bạn viết
JC Rocamonde

3
Vâng, tôi biết rằng dấu gạch dưới đơn có nghĩa / gợi ý rằng phương thức / thuộc tính phải là riêng tư (mặc dù bạn không thể thực hiện các phương thức riêng tư trong Python AFAIK), và tôi đã tự hỏi liệu đó có phải là trường hợp với (một số) dấu gạch dưới gấp đôi không.
Eduard Luca

28
@EduardLuca Double gạch dưới khi bắt đầu chỉ tương tự như một dấu gạch dưới duy nhất khi bắt đầu, nhưng thậm chí còn "riêng tư" hơn (tra cứu "xáo trộn tên python"). Dấu gạch dưới kép ở đầu và cuối là khác nhau - chúng được dành riêng cho python và không riêng tư (ví dụ: các phương thức ma thuật như __init__ và __add__).
Leassaidh Gordon

101

kiểu() ?

>>> class A(object):
...    def whoami(self):
...       print type(self).__name__
...
>>>
>>> class B(A):
...    pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>

điều này giống như thành viên trong lớp , nhưng tôi phải phân tích kết quả này bằng tay, điều này hơi khó chịu ...
Dan

8
Tôi thích cái này. Bằng cách này, có thể trong một lớp cơ sở để có được tên của lớp con.
joctee

6
hoặc self.__class__.__name__thay vì type(self).__name__để có được hành vi tương tự. Trừ khi có một cái gì đó type()chức năng mà tôi không nhận thức được?
andreb

2
Nếu bạn đang sử dụng type(item)trên một mục danh sách, kết quả sẽ là <type 'instance'>trong khi item.__class__.__name__giữ tên lớp.
Grochni

1
Tôi nghĩ rằng vấn đề mà @Grochni đề cập chỉ liên quan đến một số lớp nhất định trong Python 2.x, xem tại đây: stackoverflow.com/questions/6666856/ Lỗi
Nate CK

43
class A:
  pass

a = A()
str(a.__class__)

Mã mẫu ở trên (khi đầu vào trong trình thông dịch tương tác) sẽ tạo ra '__main__.A'trái ngược với mã 'A'được tạo nếu __name__thuộc tính được gọi. Bằng cách đơn giản chuyển kết quả của A.__class__hàm strtạo, phân tích cú pháp được xử lý cho bạn. Tuy nhiên, bạn cũng có thể sử dụng mã sau nếu bạn muốn một cái gì đó rõ ràng hơn.

"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)

Hành vi này có thể được ưa thích hơn nếu bạn có các lớp có cùng tên được xác định trong các mô-đun riêng biệt.

Mã mẫu được cung cấp ở trên đã được thử nghiệm trong Python 2.7.5.


Đã thử nghiệm trong 2.6.6. Vẫn hoạt động tốt.
Hamlett

29
type(instance).__name__ != instance.__class__.__name  #if class A is defined like
class A():
   ...

type(instance) == instance.__class__                  #if class A is defined like
class A(object):
  ...

Thí dụ:

>>> class aclass(object):
...   pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>


>>> class bclass():
...   pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>

5
Điều này chỉ đúng với Python cũ 2.x. Trong 3.x, b class () sẽ phân giải thành b class (object). Và thậm chí sau đó, các lớp mới xuất hiện trong Python 2.2.
alcalde

16

Câu hỏi hay.

Đây là một ví dụ đơn giản dựa trên GHZ có thể giúp ai đó:

>>> class person(object):
        def init(self,name):
            self.name=name
        def info(self)
            print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person

13

Ngoài ra, bạn có thể sử dụng classmethodtrang trí:

class A:
    @classmethod
    def get_classname(cls):
        return cls.__name__

    def use_classname(self):
        return self.get_classname()

Cách sử dụng :

>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'

10

Ngoài việc lấy __name__thuộc tính đặc biệt , bạn có thể thấy mình cần tên đủ điều kiện cho một lớp / hàm nhất định. Điều này được thực hiện bằng cách lấy các loại __qualname__.

Trong hầu hết các trường hợp, chúng sẽ giống hệt nhau, nhưng, khi xử lý các lớp / phương thức lồng nhau, chúng khác nhau ở đầu ra mà bạn nhận được. Ví dụ:

class Spam:
    def meth(self):
        pass
    class Bar:
        pass

>>> s = Spam()
>>> type(s).__name__ 
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__       # type not needed here
'Bar'
>>> type(s).Bar.__qualname__   # type not needed here 
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'

Vì hướng nội là những gì bạn theo đuổi, nên đây luôn là điều bạn có thể muốn xem xét.


2
Cần lưu ý rằng __qualname__dành cho Python 3.3+
FireAọ

10
Và tôi sẽ tránh đặt tên bất cứ thứ gì trong phần mềm "meth" của mình.
Bobort

Giải thích liên quan cho __qualname__vs __name__: stackoverflow.com/questions/58108488/what-is-qualname-in-python
ti7

0

Để có được tên lớp:

type(instance).__name__

hoặc là

instance.__class__.__name__

cả hai đều giống nhau

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.