pythonic способ преобразовать переменную для списка

Вы не можете безопасно сделать то, что Вы хотите, так как хэш-код по умолчанию () не может возвратить адрес и был упомянут, несколько объектов с тем же хэш-кодом возможны. Единственный способ выполнить, что Вы хотите, состоит в том, чтобы на самом деле переопределить хэш-код () метод для рассматриваемых объектов и гарантировать, что они все обеспечивают уникальные значения. Выполнимо ли это в Вашей ситуации, другой вопрос.

Для записи, я испытал несколько объектов с тем же хэш-кодом по умолчанию в VM IBM, работающем в, БЫЛ сервер. У нас был дефект, где объекты, помещаемые в удаленный кэш, перезаписать из-за этого. Это было сенсационным сообщением для меня в той точке, так как я предположил, что хэш-код по умолчанию был адресом памяти объектов также.

17
задан S.Lott 13 September 2009 в 12:50
поделиться

8 ответов

Мне нравится предложение Андрея Ваджны 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
10
ответ дан 30 November 2019 в 12:44
поделиться

Вы можете выполнять прямое сравнение типов, используя type () .

def my_func(input):
    if not type(input) is list:
        input = [input]
    for e in input:
        # do something

Однако его способ позволяет любой тип, производный от список типа для передачи. Таким образом предотвращается случайная упаковка любых производных типов.

1
ответ дан 30 November 2019 в 12:44
поделиться

Во-первых, не существует общего метода, который мог бы отличить «отдельный элемент» от «списка элементов», поскольку по определению список может быть элементом другого списка.

Я бы сказал вам необходимо определить, какие типы данных у вас могут быть, чтобы у вас могли быть:

  • любой потомок 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]
3
ответ дан 30 November 2019 в 12:44
поделиться

Ваш подход кажется мне правильным.

Это похоже на то, как вы используете атом? в Лиспе, когда вы перебираете списки и проверяете текущий элемент, чтобы убедиться, что он является списком или нет, потому что, если это список, вы тоже хотите обработать его элементы.

Так что да, не вижу в этом ничего плохого.

0
ответ дан 30 November 2019 в 12:44
поделиться

Это кажется разумным способом сделать это. Вы хотите проверить, является ли элемент списком, и это напрямую выполняется. Ситуация усложняется, если вы хотите поддерживать и другие «списковые» типы данных, например:

isinstance(input, (list, tuple))

или, в более общем смысле, абстрагироваться от вопроса:

def iterable(obj):
  try:
    len(obj)
    return True
  except TypeError:
    return False

, но опять же, в целом, ваш метод прост и правильный , что мне нравится!

-1
ответ дан 30 November 2019 в 12:44
поделиться

Это нормальный способ (не забудьте включить кортежи).

Однако вы также можете подумать, имеет ли аргумент метод __iter__ или метод __getitem__ . (обратите внимание, что строки содержат __getitem__ вместо __iter __.)

hasattr(arg, '__iter__') or hasattr(arg, '__getitem__')

Это, вероятно, наиболее общее требование для типа, подобного списку, чем только проверка типа.

0
ответ дан 30 November 2019 в 12:44
поделиться

Вы можете поставить * перед аргументом, таким образом вы всегда получите кортеж:

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))

, чтобы (неизбежно) несколько сложная логика нормализации находилась в ОДНОМ месте, как и должно быть! -)

14
ответ дан 30 November 2019 в 12:44
поделиться

Вы можете поставить * перед аргументом, таким образом, вы

2
ответ дан 30 November 2019 в 12:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: