Python: функция, которая принимает итеративный аргумент и генерирует кортежи

Довольно часто, когда я создаю файл XML из данных, хранящихся в классе, я часто получал ошибки, если атрибут не существовал или имел тип None. В этом случае моя проблема не зная, что такое имя атрибута, как указано в вашем вопросе, а скорее данные, хранящиеся в этом атрибуте.

class Pet:
    def __init__(self):
        self.hair = None
        self.color = None

Если я использовал hasattr для сделайте это, он вернет True, даже если значение атрибута имеет тип None, и это приведет к ошибке моей команды ElementTree set.

hasattr(temp, 'hair')
>>True

Если значение атрибута имело тип None, getattr также вернет его, что приведет к сбою моей команды ElementTree set.

c = getattr(temp, 'hair')
type(c)
>> NoneType

Теперь я использую следующий метод, чтобы позаботиться об этих случаях:

def getRealAttr(class_obj, class_attr, default = ''):
    temp = getattr(class_obj, class_attr, default)
    if temp is None:
        temp = default
    elif type(temp) != str:
        temp = str(temp)
    return temp

Это когда и как я использую getattr.

2
задан bryan tetris 13 July 2018 в 20:33
поделиться

5 ответов

Вы можете инициализировать словарь со счетчиками:

liste = ['a','b','a','a','b']
compte = {}
result = []
for valeur in liste:
    compte[valeur] = compte.get(valeur, 0) + 1
    result.append((valeur, compte[valeur]))

print(result)
1
ответ дан Andomar 17 August 2018 в 12:09
поделиться

Вы можете использовать Counter из модуля collections:

from collections import Counter

liste = ['a','b','a','a','b']

def counter(iterable):
    c = Counter()
    for i in iterable:
        c.update(i)
        yield i, c[i]

print(list(counter(liste)))

Выходы:

[('a', 1), ('b', 1), ('a', 2), ('a', 3), ('b', 2)]
1
ответ дан Andrej Kesely 17 August 2018 в 12:09
поделиться

Используйте функцию генератора.

from collections import defaultdict

def with_running_count(values):
    counts = defaultdict(int)
    for value in values:
        counts[value] += 1
        yield value, counts[value]

>>> print(*with_running_count('abaab'))

('a', 1) ('b', 1) ('a', 2) ('a', 3) ('b', 2)

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

# an endless iterator
coin = iter(lambda: random.choice(['heads', 'tails']), None)

# the running count will also be endless        
toss = with_running_count(coin)

>>> next(toss), next(toss), next(toss)
(('tails', 1), ('tails', 2), ('heads', 1))
2
ответ дан Håken Lid 17 August 2018 в 12:09
поделиться

Ваш ожидаемый результат - это список, а не словарь. Исправить ваш код будет использование вашего dict для подсчета, но добавление к списку:

>>> liste = ['a','b','a','a','b']
>>>
>>> compte = dict.fromkeys(liste,0) #Or use a default dict
>>> result = []
>>> for valeur in liste:
...  compte[valeur] += 1
...  result.append((valeur,compte[valeur]))
...
>>> print(result)
[('a', 1), ('b', 1), ('a', 2), ('a', 3), ('b', 2)]
3
ответ дан kabanus 17 August 2018 в 12:09
поделиться

Вы можете просто изменить свой код следующим образом:

liste = ['a','b','a','a','b']

liste2 = []
compte = {}.fromkeys(set(liste),0)
for valeur in liste:
    compte[valeur] += 1
    liste2.append(valeur + ':' + str(compte[valeur]))

print(liste2)

Важно сказать: то, что вы пытаетесь сделать, это не кортеж, а список, потому что он изменен. Ваша переменная compte является dictionary.

2
ответ дан Lorran Sutter 17 August 2018 в 12:09
поделиться
Другие вопросы по тегам:

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