Вы не можете безопасно сделать то, что Вы хотите, так как хэш-код по умолчанию () не может возвратить адрес и был упомянут, несколько объектов с тем же хэш-кодом возможны. Единственный способ выполнить, что Вы хотите, состоит в том, чтобы на самом деле переопределить хэш-код () метод для рассматриваемых объектов и гарантировать, что они все обеспечивают уникальные значения. Выполнимо ли это в Вашей ситуации, другой вопрос.
Для записи, я испытал несколько объектов с тем же хэш-кодом по умолчанию в VM IBM, работающем в, БЫЛ сервер. У нас был дефект, где объекты, помещаемые в удаленный кэш, перезаписать из-за этого. Это было сенсационным сообщением для меня в той точке, так как я предположил, что хэш-код по умолчанию был адресом памяти объектов также.
Мне нравится предложение Андрея Ваджны hasattr (var, '__ iter __')
. Обратите внимание на следующие результаты для некоторых типичных типов Python:
>>> hasattr("abc","__iter__")
False
>>> hasattr((0,),"__iter__")
True
>>> hasattr({},"__iter__")
True
>>> hasattr(set(),"__iter__")
True
Это имеет дополнительное преимущество, заключающееся в том, что строка рассматривается как не повторяемая - строки представляют собой серую область, поскольку иногда вы хотите рассматривать их как элемент, а иногда как последовательность
Обратите внимание, что в Python 3 тип str
имеет атрибут __ iter __
, и это не работает:
>>> hasattr("abc", "__iter__")
True
Вы можете выполнять прямое сравнение типов, используя type ()
.
def my_func(input):
if not type(input) is list:
input = [input]
for e in input:
# do something
Однако его способ позволяет любой тип, производный от список типа
для передачи. Таким образом предотвращается случайная упаковка любых производных типов.
Во-первых, не существует общего метода, который мог бы отличить «отдельный элемент» от «списка элементов», поскольку по определению список может быть элементом другого списка.
Я бы сказал вам необходимо определить, какие типы данных у вас могут быть, чтобы у вас могли быть:
list
против чего-либо еще
isinstance (input, list)
(так что ваш пример верен) basestring
в Python 2.x, str
в Python 3.x)
isinstance (myvar, collections.Sequence), а не isinstance (myvar, str)
int
, str
, MyClass
isinstance (input, (int, str, MyClass))
.
try:
input = iter(input) if not isinstance(input, str) else [input]
except TypeError:
input = [input]
Ваш подход кажется мне правильным.
Это похоже на то, как вы используете атом?
в Лиспе, когда вы перебираете списки и проверяете текущий элемент, чтобы убедиться, что он является списком или нет, потому что, если это список, вы тоже хотите обработать его элементы.
Так что да, не вижу в этом ничего плохого.
Это кажется разумным способом сделать это. Вы хотите проверить, является ли элемент списком, и это напрямую выполняется. Ситуация усложняется, если вы хотите поддерживать и другие «списковые» типы данных, например:
isinstance(input, (list, tuple))
или, в более общем смысле, абстрагироваться от вопроса:
def iterable(obj):
try:
len(obj)
return True
except TypeError:
return False
, но опять же, в целом, ваш метод прост и правильный , что мне нравится!
Это нормальный способ (не забудьте включить кортежи).
Однако вы также можете подумать, имеет ли аргумент метод __iter__ или метод __getitem__ . (обратите внимание, что строки содержат __getitem__ вместо __iter __.)
hasattr(arg, '__iter__') or hasattr(arg, '__getitem__')
Это, вероятно, наиболее общее требование для типа, подобного списку, чем только проверка типа.
Вы можете поставить * перед аргументом, таким образом вы всегда получите кортеж:
def a(*p):
print type(p)
print p
a(4)
>>> <type 'tuple'>
>>> (4,)
a(4, 5)
>>> <type 'tuple'>
>>> (4,5,)
Но это заставит вас вызвать вашу функцию с переменными параметрами, я не Не знаю, приемлемо ли это для вас.
def a(*p):
print type(p)
print p
a(4)
>>> <type 'tuple'>
>>> (4,)
a(4, 5)
>>> <type 'tuple'>
>>> (4,5,)
Но это заставит вас вызвать функцию с переменными параметрами, я не знаю, приемлемо ли это для вас.
def a(*p):
print type(p)
print p
a(4)
>>> <type 'tuple'>
>>> (4,)
a(4, 5)
>>> <type 'tuple'>
>>> (4,5,)
Но это заставит вас вызвать функцию с переменными параметрами, я не знаю, приемлемо ли это для вас.
все без изменения ФАКТИЧЕСКОГО входного списка (если список действительно был ;-). Если все, что вам нужно, это один простой цикл для
, тогда этот последний шаг не нужен (и действительно бесполезен, если, например, ввод - это огромный открытый файл), и я бы предложил вместо него вспомогательный генератор:
def justLoopOn(input):
if isinstance(input, basestring):
yield input
else:
try:
for item in input:
yield item
except TypeError:
yield input
теперь в каждую из ваших функций, требующих такой нормализации аргументов, вы просто используете:
for item in justLoopOn(input):
Вы можете использовать вспомогательную функцию нормализации даже в другом случае (где вам нужен реальный список для дальнейших гнусных целей); на самом деле, в таких (более редких) случаях вы можете просто сделать:
thelistforme = list(justLoopOn(input))
, чтобы (неизбежно) несколько сложная логика нормализации находилась в ОДНОМ месте, как и должно быть! -)
input - это огромный открытый файл), и вместо этого я бы предложил вспомогательный генератор:def justLoopOn(input):
if isinstance(input, basestring):
yield input
else:
try:
for item in input:
yield item
except TypeError:
yield input
теперь в каждой из ваших функций, нуждающихся в такой нормализации аргументов, вы просто используете:
for item in justLoopOn(input):
Вы можете использовать вспомогательную функцию нормализации даже в другой случай (где вам нужен реальный список для дальнейших гнусных целей); на самом деле, в таких (более редких) случаях вы можете просто сделать:
thelistforme = list(justLoopOn(input))
, чтобы (неизбежно) несколько сложная логика нормализации находилась в ОДНОМ месте, как и должно быть! -)
input - это огромный открытый файл), и вместо этого я бы предложил вспомогательный генератор:def justLoopOn(input):
if isinstance(input, basestring):
yield input
else:
try:
for item in input:
yield item
except TypeError:
yield input
теперь в каждой из ваших функций, нуждающихся в такой нормализации аргументов, вы просто используете:
for item in justLoopOn(input):
Вы можете использовать вспомогательную функцию нормализации даже в другой случай (где вам нужен реальный список для дальнейших гнусных целей); на самом деле, в таких (более редких) случаях вы можете просто сделать:
thelistforme = list(justLoopOn(input))
, чтобы (неизбежно) несколько сложная логика нормализации находилась в ОДНОМ месте, как и должно быть! -)
Вы можете поставить * перед аргументом, таким образом, вы