як дізнатися, чи є змінна кортежем, рядком чи цілим числом?


78

Я намагаюся з'ясувати невідповідність типу, додаючи рядок до іншого рядка в операції конкатенації.

В основному повертається помилка TypeError(не може об'єднати рядок і кортеж); тому я хотів би зрозуміти, де я призначив значення як кортеж замість рядка.

Всі значення, які я присвоюю, є рядками, тому я повинен з'ясувати, звідки береться кортеж, тому я сподівався, що в Python є спосіб дізнатись, що міститься в змінній і який це тип.

Наразі за допомогою pdb мені вдалося перевірити вміст змінних, і я правильно отримую ті значення, які я очікував; але я хотів би знати також тип змінної (за логікою, якщо компілятор може викликати помилку типу, це означає, що він знає, що знаходиться всередині змінної і чи сумісна вона з виконаною операцією; повинен бути способом отримати це значення / прапор).

Чи є спосіб роздрукувати тип змінної в python?

До речі, я намагався змінити всі свої змінні на явно рядки, але це неможливо примусити str (myvar), тому я не можу просто відтворювати як тип рядка скрізь, де я використовую рядки.

python 

2
Не бажаючи бути вибагливими, але змінні ніколи не мають типу в Python, це роблять лише об’єкти (на які посилаються змінні). Через це немає реальних типів закидів, лише функції перетворення об'єктів.
Юрген Стробель

Справді Юрген; Я не до кінця знаю, як python працює під капотом, але я припускаю, що це об'єктно-орієнтована мова, тому, коли я створюю змінну, вона створюватиме об'єкт правильного типу даних і посилатиметься на нього вказівником, тому, коли я використовую змінна я фактично використовую екземпляр рядка об'єкта (або будь-якого іншого типу даних).

Відповіді:


42

Ви просто використовуєте:

type(varname)

який буде виводити int, str, float тощо ...


Використовувати __class__майже завжди краще, ніж використовувати, typeоскільки в більшості ситуацій вони повертають одне і те ж, за винятком того type, що тип усіх класів старого стилю буде оголошено як "екземпляр". зверніться до цього SO-питання
Даррен Інь,

@DarrenYin Це неправда, type(o)і o.__class__ завжди повертати одне і те ж. Найбільш прихильна відповідь у зв’язаному питанні говорить про це, але вона не існувала, коли ви пов’язували її. Крім того, typeпотрібно менше друкувати і виглядає як загальнодоступна функція API (без підкреслення).
WloHu

174
isinstance(obj, tuple)
isinstance(obj, basestring)
isinstance(obj, int)

Дякую за відповідь; це чудово підходить для перевірки під час запуску програми, але я намагаюся отримати значення під час налагодження за допомогою pdb. Це чудовий спосіб уникнути проблеми!

28

використовувати isinstance?

if isinstance(var, int):

if isinstance(var, str):

if isinstance(var, tuple):

Тестування на strпомилки на unicodeрядках не відбудеться . Крім того, isinstance(var, tuple)буде пропускати будь-які змінні, які трапляються lists, які часто виникають у таких ситуаціях. Звичайно, ви можете помилитися, якщо var є екземпляром a list, але добре бути впевненим, що ви знаєте, що буде відбуватися в різних ситуаціях.
Даррен Інь,

5
У Python 3 ви можете використовувати послідовність типів для тестування:isinstance(var, (tuple, list))
bugmenot123

Забавно, що інший хлопець отримує всі голоси, хоча ти відповів першим.
qwerty_so

10

Зверніть увагу, якщо ви хочете перевірити свій тип var в операторі if, конструкція if type(varname) == "tuple":не буде працювати. Але це:

if type(varname) is tuple:
if type(varname) is list:
if type(varname) is dict:
if type(varname) is int:
if type(varname) is str:

4
Натомість слід справді використовувати isinstance. type () небезпечний, коли справа стосується спадкування.
bugmenot123

@ bugmenot123, я не висвітлюю всі можливі результати, я зазначаю про помилку, яку люди зазвичай роблять при спробі перевірити тип, а потім дивуються, коли вона не працює. В іншому випадку ви абсолютно праві.
Goujon

Сподіваюсь, ви не проти, але я відповів на вашу відповідь власноруч і відповів за іншою методологією. Якщо ви заперечуєте, я видалю посилання. Дякую.
WinEunuuchs2Unix

@ WinEunuuchs2Unix, незважаючи на те, що, на мій погляд, заміна "є" на "==" - це не інша методологія, я зовсім не проти.
Goujon

4

Ви, мабуть, хочете протестувати (припускаючи Python 2.x) за допомогою isinstance(obj, basestring). У вас є варіанти використання isinstance, typeта виклику атрибута __class__, але isinstance, швидше за все, тут ви бажаєте. Погляньте на цю статтю для більш ретельного вивчення відмінностей між трьома варіантами.


Спасибі Даррен; Я, напевно, проведу тестування, використовуючи вашу пропозицію, але на даний момент я використовую pdb; так що я можу зрозуміти, який з них є проблематичним, і уникати робити ту саму помилку (мені подобається захисне кодування, але в той же час я волію уникати помилок у першій інстанції, замість того, щоб покладатися на перевірку, щоб уловити помилка). Цікаво, що існує також атрибут class ; ніколи про це не чув.

1

repr (об'єкт) дасть текстовий опис об'єкта, який повинен відображати тип і значення. Ви можете роздрукувати або переглянути це в налагоджувачі.

Для простих значень repr, як правило, повертає той самий рядок, що і ви писали б значення буквально в коді. Для користувацьких класів він надає ім'я класу та ідентифікатор об'єкта або щось інше, якщо клас є

__repr__

замінено.


Дякую за відповідь Юрген. Я спробував repr, але він повертає мені значення змінної * у моєму випадку рядок), тому робить те саме, що робить p (varname) ... я роблю щось не так, оскільки я повинен бачити, як ви вже згадали, type, значення та опис об’єкта?

1
Ні. Він повертає строковий літерал для str або unicode, включаючи лапки, тому ви повинні визнати його таким типом. Він повертає цифри без котирувань для цілочисельних типів і подібні для інших числових типів. Для користувацького класу A він повертає щось на зразок <екземпляр mymodule.A за адресою 0x123456> за замовчуванням, але деякі класи переписують цей рядок опису.
Юрген Стробель

-2

Щоб доповнити відповідь Гуджона, розглянемо цей список змішаних цілих чи кортежів:

for f in fills:
    print (type(f), f)
    if type(f)==int : print "INTEGER!!!"

Генерує цей результат:

(<type 'int'>, 0)
INTEGER!!!
(<type 'tuple'>, (62973, 39058, 25708, 102))
(<type 'int'>, 1)
INTEGER!!!
(<type 'tuple'>, (16968, 12069, 3329, 102))
(<type 'int'>, 2)
INTEGER!!!
(<type 'tuple'>, (24939, 62205, 30062, 102))
(<type 'tuple'>, (32911, 32911, 0, 153))
(<type 'tuple'>, (32911, 0, 0, 153))
(<type 'tuple'>, (32911, 0, 32911, 153))
(<type 'tuple'>, (65535, 0, 0, 153))
(<type 'tuple'>, (0, 0, 65535, 153))
(<type 'tuple'>, (0, 32911, 0, 153))
(<type 'tuple'>, (0, 65535, 65535, 153))

Тож секрет полягає не в тестуванні на "int"рядок символів, а натомість у тестуванні на intключове слово. Якщо ви схожі на мене і переходите зі сценарію Bash, використання ==тестів у світі сценаріїв Python, мабуть, стане вашим першим кроком.


1
Ви неправильно прочитали відповідь Гуджона. Вони спеціально написали, "конструкція, якщо тип (ім'я варіанта) ==" кортеж ": не буде працювати" , а потім пояснили правильний спосіб.
kaya3

@ kaya3 У своїй відповіді я намагався сказати, якщо ви видалите "подвійні лапки, це спрацює.
WinEunuuchs2Unix

2
Я зрозумів, що ви написали у своїй відповіді; це неправильно, тому що ви говорите, що відповідь Гуджона зробив цю помилку, а насправді відповідь Гуджона визначила, що це помилка . Ваше виправлення те саме, що написав Гуджон як рішення цієї проблеми.
kaya3

@ kaya3 Я переформулював відповідь і пояснив, чому ==це важливо для таких людей, як я. Чи нормально зараз?
WinEunuuchs2Unix

1
Ваша відповідь більше не помилкова, але незрозуміло, що ви додали до існуючої відповіді, крім того, що ви можете використовувати ==замість цього, isякщо хочете. Практичної різниці немає, крім дуже рідкісних крайових випадків, і в цих випадках isце правильний вибір.
kaya3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.