จะกำหนดชนิดของตัวแปร Python ได้อย่างไร?


1567

ฉันจะดูชนิดของตัวแปรได้อย่างไรว่าเป็น 32 บิตที่ไม่ได้ลงชื่อ, 16 บิตที่เซ็นชื่อ ฯลฯ

ฉันจะดูมันได้อย่างไร


มีความเป็นไปได้ที่ซ้ำกันของวิธีตรวจสอบแบบ canonical ใน Python คืออะไร
Georgy

คำตอบ:


1379

ใช้type()ฟังก์ชั่น builtin:

>>> i = 123
>>> type(i)
<type 'int'>
>>> type(i) is int
True
>>> i = 123.456
>>> type(i)
<type 'float'>
>>> type(i) is float
True

ในการตรวจสอบว่าตัวแปรเป็นประเภทที่กำหนดให้ใช้isinstance:

>>> i = 123
>>> isinstance(i, int)
True
>>> isinstance(i, (float, str, set, dict))
False

โปรดทราบว่า Python ไม่มีประเภทเดียวกันกับ C / C ++ ซึ่งดูเหมือนจะเป็นคำถามของคุณ


437

คุณอาจกำลังมองหาฟังก์ชั่นในตัวtype()

ดูตัวอย่างด้านล่าง แต่ไม่มีประเภท "unsigned" ใน Python เหมือนกับ Java

จำนวนเต็มบวก:

>>> v = 10
>>> type(v)
<type 'int'>

จำนวนเต็มบวกขนาดใหญ่ :

>>> v = 100000000000000
>>> type(v)
<type 'long'>

จำนวนเต็มลบ:

>>> v = -10
>>> type(v)
<type 'int'>

ลำดับตัวอักษร:

>>> v = 'hi'
>>> type(v)
<type 'str'>

จำนวนเต็มทศนิยม:

>>> v = 3.14159
>>> type(v)
<type 'float'>

ฉันต้องทำสองครั้งเมื่อเห็นสิ่งนี้ ตอนนี้ Java SE8 มีจำนวนเต็มที่ไม่ได้ลงนามและฉันได้พัฒนาขึ้นมากจนดูเหมือนว่าเป็นบาปที่ Java ไม่เคยมีจำนวนเต็มที่ไม่ได้ลงชื่อก่อน SE8
dddJewelsbbb


110

จะกำหนดประเภทของตัวแปรใน Python ได้อย่างไร?

ดังนั้นหากคุณมีตัวแปรตัวอย่างเช่น:

one = 1

คุณต้องการทราบประเภทของมันหรือไม่?

มีวิธีที่ถูกและผิดวิธีในการทำทุกอย่างใน Python นี่คือวิธีที่ถูกต้อง:

ใช้ type

>>> type(one)
<type 'int'>

คุณสามารถใช้__name__คุณสมบัติเพื่อรับชื่อของวัตถุ (นี่เป็นหนึ่งในคุณสมบัติพิเศษไม่กี่อย่างที่คุณต้องใช้__dunder__ชื่อเพื่อไป - ไม่มีแม้แต่วิธีการในinspectโมดูล)

>>> type(one).__name__
'int'

อย่าใช้ __class__

ใน Python ชื่อที่ขึ้นต้นด้วยเครื่องหมายขีดล่างนั้นไม่ได้เป็นส่วนหนึ่งของ API สาธารณะและเป็นแนวทางปฏิบัติที่ดีที่สุดสำหรับผู้ใช้ที่จะหลีกเลี่ยงการใช้ (ยกเว้นเมื่อจำเป็นจริงๆ)

เนื่องจากtypeให้คลาสของวัตถุแก่เราเราควรหลีกเลี่ยงสิ่งนี้โดยตรง :

>>> one.__class__

นี่เป็นความคิดแรกที่ผู้คนมีเมื่อเข้าถึงประเภทของวัตถุในวิธีการ - พวกเขากำลังมองหาคุณลักษณะอยู่แล้วดังนั้นประเภทจึงดูเหมือนแปลก ๆ ตัวอย่างเช่น:

class Foo(object):
    def foo(self):
        self.__class__

อย่า ให้พิมพ์ (ตัวเอง) แทน:

class Foo(object):
    def foo(self):
        type(self)

รายละเอียดการใช้งานของ ints และลอย

ฉันจะดูชนิดของตัวแปรได้อย่างไรว่าเป็น 32 บิตที่ไม่ได้ลงชื่อ, 16 บิตที่เซ็นชื่อ ฯลฯ

ใน Python รายละเอียดเฉพาะเหล่านี้เป็นรายละเอียดการนำไปปฏิบัติ โดยทั่วไปแล้วเราไม่ต้องกังวลเกี่ยวกับเรื่องนี้ใน Python อย่างไรก็ตามเพื่อป้อยอความอยากรู้ของคุณ ...

ใน Python 2 int มักจะเป็นจำนวนเต็มที่ลงนามเท่ากับความกว้างของการปรับใช้คำ (จำกัด โดยระบบ) ก็มักจะนำมาใช้เป็นเวลานานใน C เมื่อจำนวนเต็มใหญ่กว่านี้เรามักจะแปลงให้เป็น Python longs (ด้วยความแม่นยำไม่ จำกัด ไม่ต้องสับสนกับ C longs)

ตัวอย่างเช่นใน Python 2 32 บิตเราสามารถอนุมานได้ว่า int เป็นจำนวนเต็ม 32 บิตที่ได้รับการเซ็นชื่อ:

>>> import sys

>>> format(sys.maxint, '032b')
'01111111111111111111111111111111'
>>> format(-sys.maxint - 1, '032b') # minimum value, see docs.
'-10000000000000000000000000000000'

ใน Python 3 int เก่าจะหายไปและเราเพิ่งใช้ (Python) ตราบเท่าที่ int ซึ่งมีความแม่นยำไม่ จำกัด

นอกจากนี้เรายังสามารถรับข้อมูลบางอย่างเกี่ยวกับ Python Floats ซึ่งโดยปกติจะใช้เป็นสองเท่าใน C:

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, 
min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, 
mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

ข้อสรุป

อย่าใช้__class__API เชิงความหมายที่ไม่ใช่สาธารณะเพื่อรับชนิดของตัวแปร ใช้typeแทน

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


ประเภทออกมา<type instance>แต่__class__ให้email.message.Message- ฉันทำอะไรผิด
Jasen

@ Jasen คุณใช้ Python 2 และไม่สืบทอดมาจากobjectไหน?
Aaron Hall

ใช่เพียงแค่import email ไม่ใช้คลาสของการประดิษฐ์ของฉันเอง
Jasen

65
print type(variable_name)

ฉันยังขอแนะนำให้ล่ามแบบอินเทอร์แอคทีฟIPythonเมื่อจัดการกับคำถามเช่นนี้ มันช่วยให้คุณพิมพ์variable_name?และจะกลับรายการข้อมูลทั้งหมดเกี่ยวกับวัตถุรวมถึงประเภทและสตริง doc สำหรับประเภท

เช่น

In [9]: var = 123

In [10]: var?
Type:       int
Base Class: <type 'int'>
String Form:    123
Namespace:  Interactive
Docstring:
    int(x[, base]) -> integer

แปลงสตริงหรือตัวเลขเป็นจำนวนเต็มถ้าเป็นไปได้ อาร์กิวเมนต์ floating point จะถูกปัดเศษเป็นศูนย์ (ซึ่งไม่รวมถึงการแทนสตริงของตัวเลขทศนิยม!) เมื่อทำการแปลงสตริงให้ใช้ฐานที่เป็นตัวเลือก มันเป็นข้อผิดพลาดในการระบุฐานเมื่อแปลงสตริงที่ไม่ใช่ หากอาร์กิวเมนต์อยู่นอกช่วงจำนวนเต็มวัตถุแบบยาวจะถูกส่งคืนแทน


2
ฉันขอ int ที่ไม่ได้ลงชื่อ, ลงนาม int ฯลฯ
user46646

3
print type(str)ส่งคืนข้อผิดพลาดใน Python 3.6 ใช้type(str)
Kolob Canyon

4
@KolobCanyon นั่นเป็นเพราะใน 3.x, พิมพ์ต้องการวงเล็บ:print(type(str))
jcoppens

1
คุณควรแก้ไขprint type(var)โค้ดที่ผิดพลาดจริงๆ
ฮัน XIAO


40

อีกวิธีหนึ่งโดยใช้__class__:

>>> a = [1, 2, 3, 4]
>>> a.__class__
<type 'list'>
>>> b = {'key1': 'val1'}
>>> b.__class__
<type 'dict'>
>>> c = 12
>>> c.__class__
<type 'int'>

1
Re: แสดงความคิดเห็น"ชื่อที่ขึ้นต้นด้วยขีดล่าง ... " (เดี่ยว) ขีดล่างมีความแตกต่างอย่างมากจากขีดเส้นใต้คู่ ("ดัน") และพวกเขาเป็นส่วนหนึ่งของ API สาธารณะอย่างแน่นอนและใช้งานได้ดี นี่อาจช่วยได้ ... youtu.be/wf-BqAjZb8M
michael

31

ตัวอย่างการตรวจสอบประเภทอย่างง่ายใน Python:

assert type(variable_name) == int

assert type(variable_name) == bool

assert type(variable_name) == list

29

มันอาจจะไม่เกี่ยวข้องเล็กน้อย แต่คุณสามารถตรวจสอบประเภทของวัตถุที่มีisinstance(object, type)ตามที่กล่าวไว้ที่นี่


1
ฉันคิดว่าอันนี้ดีกว่าฟังก์ชั่นประเภทเพื่อใช้ในการตรวจสอบกระบวนการ หากคุณต้องการตรวจสอบและดำเนินการกับผลลัพธ์ที่คุณต้องใช้ลองจับกับชนิด แต่ isinstance ส่งคืนจริงหรือเท็จ
244196

24

คำถามค่อนข้างคลุมเครือ - ฉันไม่แน่ใจว่าคุณหมายถึงอะไรโดย "ดู" หากคุณพยายามสอบถามประเภทของวัตถุ Python ดั้งเดิมคำตอบของ@atzzจะนำคุณไปในทิศทางที่ถูกต้อง

อย่างไรก็ตามหากคุณกำลังพยายามสร้างวัตถุ Python ที่มีความหมายของ C-types ดั้งเดิม (เช่นuint32_t, int16_t) ให้ใช้structโมดูล คุณสามารถกำหนดจำนวนบิตใน C-type ดั้งเดิมได้ดังนี้:

>>> struct.calcsize('c') # char
1
>>> struct.calcsize('h') # short
2
>>> struct.calcsize('i') # int
4
>>> struct.calcsize('l') # long
4

สิ่งนี้ยังสะท้อนให้เห็นในarrayโมดูลซึ่งสามารถสร้างอาร์เรย์ของชนิดระดับล่างเหล่านี้:

>>> array.array('c').itemsize # char
1

จำนวนเต็มสูงสุดที่สนับสนุน (งูหลาม 2 int) จะได้รับโดยsys.maxint

>>> import sys, math
>>> math.ceil(math.log(sys.maxint, 2)) + 1 # Signedness
32.0

นอกจากนี้ยังมีsys.getsizeofซึ่งส่งคืนขนาดที่แท้จริงของวัตถุPythonในหน่วยความจำคงเหลือ:

>>> a = 5
>>> sys.getsizeof(a) # Residual memory.
12

สำหรับข้อมูลลอยและข้อมูลความแม่นยำใช้sys.float_info :

>>> sys.float_info
sys.floatinfo(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.2204460492503131e-16, radix=2, rounds=1)

7
คำถามที่ฉันเข้าใจนั้นถามเกี่ยวกับการสืบค้นประเภทของ "ตัวแปร" ใน Python โดยทั่วไปคำตอบของคุณถูกต้อง แต่ไม่อยู่ในหัวข้อ
tzot

19

คุณหมายถึงในPythonหรือใช้ctypes ?

ในกรณีแรกคุณไม่สามารถทำได้ - เพราะ Python ไม่ได้ลงชื่อ / ไม่ได้ลงทะเบียน 16/32 บิต

ในกรณีที่สองคุณสามารถใช้type():

>>> import ctypes
>>> a = ctypes.c_uint() # unsigned int
>>> type(a)
<class 'ctypes.c_ulong'>

สำหรับการอ้างอิงเพิ่มเติมเกี่ยวกับ ctypes, ประเภทให้ดูเอกสารอย่างเป็นทางการ


15

Python ไม่มีประเภทเช่นที่คุณอธิบาย มีสองประเภทที่ใช้ในการแสดงค่าสำคัญ: intซึ่งสอดคล้องกับประเภท int ของแพลตฟอร์มใน C และlongซึ่งเป็นจำนวนเต็มความแม่นยำโดยพลการ (เช่นมันเติบโตตามที่ต้องการและไม่มีขีด จำกัด บน) ints จะถูกแปลงเงียบไปถ้าการแสดงออกผลิตผลที่ไม่สามารถเก็บไว้ในlongint



10

ขึ้นอยู่กับว่าคุณหมายถึงระดับใด ใน Python 2.x มีจำนวนเต็มสองชนิดint(ถูก จำกัด ด้วย)sys.maxint ) และlong(ไม่จำกัดความแม่นยำ) ด้วยเหตุผลทางประวัติศาสตร์ ในรหัสไพ ธ อนสิ่งนี้ไม่ควรสร้างความแตกต่างเพราะล่ามจะแปลงเป็นแบบยาวโดยอัตโนมัติเมื่อตัวเลขมีขนาดใหญ่เกินไป หากคุณต้องการทราบเกี่ยวกับชนิดข้อมูลจริงที่ใช้ในล่ามพื้นฐานนั่นขึ้นอยู่กับการใช้งาน (CPython อยู่ใน Objects / intobject.c และ Objects / longobject.c.) เพื่อหาข้อมูลเกี่ยวกับประเภทของระบบดูที่คำตอบ cdleary สำหรับการใช้โมดูล struct



-29

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

หากคุณยืนยันในการตรวจสอบประเภทที่แน่นอนและวางifที่นี่สกปรกและที่นั่นคุณสามารถใช้__class__คุณสมบัติหรือtypeฟังก์ชั่นที่จะทำ แต่ในไม่ช้าคุณจะพบว่าตัวเองอัปเดตทั้งหมดเหล่านี้ifมีกรณีเพิ่มเติมทุกสองหรือสาม การดำเนินการด้วยวิธี OO จะป้องกันและอนุญาตให้คุณกำหนดคลาสใหม่สำหรับอินพุตประเภทใหม่แทน


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