- 001
- 002
- 003
- 004
- 005
- 006
- 007
- 008
- 009
- 010
- 011
- 012
- 013
- 014
- 015
- 016
- 017
- 018
- 019
- 020
- 021
- 022
- 023
- 024
- 025
- 026
- 027
- 028
- 029
- 030
- 031
- 032
- 033
- 034
- 035
- 036
- 037
- 038
- 039
- 040
- 041
- 042
- 043
- 044
- 045
- 046
- 047
- 048
- 049
- 050
- 051
- 052
- 053
- 054
- 055
- 056
- 057
- 058
- 059
- 060
- 061
- 062
- 063
- 064
- 065
- 066
- 067
- 068
- 069
- 070
- 071
- 072
- 073
- 074
- 075
- 076
- 077
- 078
- 079
- 080
- 081
- 082
- 083
- 084
- 085
- 086
- 087
- 088
- 089
- 090
- 091
- 092
- 093
- 094
- 095
- 096
- 097
- 098
- 099
- 100
class DictOfLists(defaultdict): # it's possible to use dict instead
def __init__(self, *args, **kwds):
__args=self.__check_args(*args)
self.__check_kwds(**kwds)
defaultdict.__init__(self,(lambda:[]), *__args, **kwds)
# dict.__init__(self, *__args, **kwds)
def __is_valid_item(self,item):
if len(item)==2 and not hasattr(item[0],"__iter__") and hasattr(item[1],"__iter__"):
return True
return False
def __check_args(self,*args):
if len(args)>1:
if type(args) == tuple and self.__is_valid_item(args):
return [args,] # tuple of key and list of values
else:
raise TypeError("Item of %s must be a tuple of (key,IterableValue) but %s=%s is not"%\
(self.__class__.__name__,
args.__class__.__name__,
repr(args)))
if len(args) != 1: return args
if isinstance(args[0], DictOfLists): return args
if hasattr(args[0],"__iter__"):
if len(args[0]) == 0: return args # empty iterator
items = args[0].items() if type(args[0]) == dict else args[0]
if self.__is_valid_item(items):
return [args,] # tuple of key and list of values
for v in items:
if not (type(v) == tuple and len(v)==2):
raise TypeError("Item of %s must be a tuple of (key, IterableValue) but %s=%s is not"%\
(self.__class__.__name__,
v.__class__.__name__,
v))
if not hasattr(v[1],"__iter__"):
raise TypeError("Value of %s must be iterable but %s(%s) is not"%\
(self.__class__.__name__,
v[1].__class__.__name__,
repr(v[1])))
else: raise TypeError(" %s must be initialized by {},[],() or %s but %s is not"%\
(self.__class__.__name__,
self.__class__.__name__,
args[0].__class__.__name__))
return args
def __check_kwds(self, **kwds):
for v in kwds.itervalues():
if not hasattr(v,"__iter__"):
raise TypeError("Value of %s must be iterable but %s(%s) is not"%\
(self.__class__.__name__,
v.__class__.__name__,
repr(v)))
def walk(self):
for k, v in self.iteritems():
for x in v:
yield k, v, x
raise StopIteration
def __setitem__(self, *args, **kwargs):
self.__check_args(*args)
self.__check_kwds(**kwargs)
return dict.__setitem__(self, *args, **kwargs)
def update(self, *args, **kwds):
_args=self.__check_args(*args)
self.__check_kwds(**kwds)
dict.update(self,*_args, **kwds)
correct = [ {}, [], (), # empty iterable
{'k2':[], 'k22':[]}, # multipe items dict
[('k3',[]),('k32',[])], # array tuples key list val
(('k4',[]),('k42',[])), # tuple of tuples key list val
('k5',[]) # tuple of key list val
]
strange = [('e0','12'), ('e1','123')]
import inspect
def init_tester(dict_class,t_array,cs):
print "\n%s %s %s"%( inspect.currentframe().f_code.co_name, dict_class().__class__.__name__, cs )
for i in t_array:
try:
print repr(i).ljust(26), repr(dict_class(i)).ljust(74),
print ' work '.ljust(8)
except Exception,e:
print "dosn't work ",
print e
continue
print "------------------------------"
if __name__ == '__main__':
init_tester( DictOfLists, correct, "correct")
init_tester( dict, correct, "correct")
init_tester( DictOfLists, strange, "strange")
init_tester( dict, strange, "strange")
Вот такой вот словарь, значениями элементов которого могут быть только списки. В принципе легко его доделать, чтобы знаечениями были все iterable, но не строки. Кроме этого, он внимательнее проверяет агрументы. Например если ему послать ('k5',[]), он воспримет это как: k5 - key, [] - value. Build-in dict например воспринимает ('12','34') как 1 - key, 2 - value, 3 - key, 4 - value. Соответственно если ему послать ('12','345'), он ругнется. Мне показалось, что это немного странное поведение, трактовать 2-х символьные строки, как key-value. Покритикуйте please. В том числе "стиль" и "красоту".
Dummy00001 06.12.2014 03:38 # +1
guest 06.12.2014 07:38 # +4
apgurman 08.12.2014 21:03 # 0
Dummy00001 08.12.2014 21:29 # 0
bormand 08.12.2014 22:51 # 0
apgurman 09.12.2014 03:20 # 0
guest 09.12.2014 03:24 # 0
Ответил в другом треде. Так блин тупо проверь на isinstance(param, basestring)
apgurman 09.12.2014 03:36 # 0
bormand 09.12.2014 06:29 # 0
Проблема с передачей тупла вместо списка - самое настоящее ССЗБ: ты нарушил контракт какой-то из своих функций. Так что смирись с гибкостью питона, пиши докстринги, соблюдай описанные в них контракты и делай тест кейсы в других местах. А твой класс ненужен.
P.S. Ну либо перелезь на более строгий язык типа c#.
apgurman 09.12.2014 06:59 # 0
bormand 09.12.2014 07:23 # +1
У нас тут свобода слова. Что хотим, то и обсуждаем. Одно время отношения Лура и Кузи обсуждали в теме про SQL иньекции в PHP...
С требованиями милости просим на платные сервисы code review.
apgurman 09.12.2014 07:29 # −2
guest 09.12.2014 16:57 # 0
guest 09.12.2014 17:08 # +1
defecate-plusplus 10.12.2014 01:25 # 0
3.14159265 10.12.2014 02:23 # +1
Пока Он не познакомил Её с флюент-интерфейсом.
guest 09.12.2014 13:04 # +1
apgurman 09.12.2014 23:59 # 0
guest 31.12.2014 03:58 # 0
>Остальное, надеался, будет понятно из кода.
Все еще непонятно, что должен делать класс, и что из этого не может стандартная библиотека.
guest 09.12.2014 13:03 # +1
apgurman 06.12.2014 06:57 # 0
Dummy00001 06.12.2014 14:00 # +1
apgurman 08.12.2014 21:05 # 0
Dummy00001 08.12.2014 21:28 # 0
apgurman 08.12.2014 21:39 # 0
Dummy00001 08.12.2014 22:32 # 0
Как перловщику, мне весь питон видится странным.
bormand 08.12.2014 22:36 # 0
А ошибка там из-за того, что ты запустил на питоне 3.х, (а для 2.х там не хватает строчки с импортом).
http://ideone.com/W00KYy
Dummy00001 08.12.2014 22:46 # +1
Не рожал. Природа не угодила - мужиком родился. Как следствие "матёрым" по определению быть не могу.
Да и в перле таких проблем нет, так как там строки есть просто строки. И только если попросить - списки.
bormand 08.12.2014 22:54 # 0
> Природа не угодила - мужиком родился.
О_о. http://ru.wiktionary.org/wiki/матёрый
Dummy00001 08.12.2014 23:03 # 0
> О_о. http://ru.wiktionary.org/wiki/матёрый
странно. "матёрый" == "мать" == "рожамшая". какое нелогичное слово.
guest 09.12.2014 02:36 # 0
apgurman 08.12.2014 22:38 # 0
bormand 08.12.2014 22:39 # 0
guest 06.12.2014 07:39 # 0
Зачем последняя строка?
apgurman 06.12.2014 08:06 # 0
guest 06.12.2014 21:16 # 0
bormand 06.12.2014 21:21 # 0
guest 06.12.2014 21:28 # 0
SyntaxError: 'return' with argument inside generator
А почему, кстати?
kyzi007 08.12.2014 12:14 # 0
apgurman 08.12.2014 20:30 # 0
guest 08.12.2014 20:42 # +1
apgurman 08.12.2014 21:04 # 0
bormand 08.12.2014 21:30 # 0
Полный пример, на котором проявляется бага, можешь кинуть?
P.S. dict(('12', '34')) что ли? А в чем смысл так писать?
wvxvw 08.12.2014 21:32 # 0
Глядя на это - я не вижу смысла специально предотвращать вышеописаное поведение - вряд ли кто-то специально будет ожидать именно то, или другое поведение от словаря, если его инициализировать с какими-то странными входными данными. И поэтому, все эти проверки кажутся лишними. Я бы максимум написал бы что-нибудь типа:
И этим бы и ограничился.
apgurman 08.12.2014 21:46 # 0
bormand 08.12.2014 21:51 # +1
bormand 08.12.2014 21:56 # 0
collections.defaultdict посмотри, тебе понравится. Там твой dict of lists в первом же примере.
apgurman 08.12.2014 22:01 # 0
wvxvw 08.12.2014 22:42 # 0
С таким сообщением об ошибке нужно часами сидеть разбираться? Чет мне слухи кажутся сильно преувеличеными.
Я не вижу чем этот надежнее встроенного. В чем выражается надежность?
ПС. Бессмысленно и даже не совсем правильно проверять так на возможность итерации. Просто это вообще не нужно проверять - если цикл не возможен, то будет соответствующая ошибка со знакомым и понятным описанием. Еще хуже будет, если repr(v) бросит исключение - вот тогда можно будет по-настоящему запутаться.
guest 09.12.2014 02:37 # 0
Вообще duck typing имеет свои минусы тоже, иной раз опечатаешься, подашь dict вместо set или наоборот, а потом со стектрейса хуеешь.
guest 09.12.2014 02:39 # 0
apgurman 09.12.2014 03:30 # 0
guest 09.12.2014 13:08 # +2
- так а хуле, может, сразу в стандартную поставку пистона добавить?
apgurman 09.12.2014 23:49 # 0
apgurman 08.12.2014 22:37 # 0
bormand 08.12.2014 22:41 # 0
apgurman 09.12.2014 03:32 # 0