Здравствуйте, Курилка, Вы писали:
К>Программисты из LShift собрали (не очень короткий) список из ньюансов, неожиданностей и неинтуитивных вещей в python.
По-моему некоторые "заморочки" весьма странные... Вытекают скорее из незнания основ языка, чем являются реальными заморочками
Здравствуйте, race1, Вы писали:
К>>Программисты из LShift собрали (не очень короткий) список из ньюансов, неожиданностей и неинтуитивных вещей в python.
R>По-моему некоторые "заморочки" весьма странные... Вытекают скорее из незнания основ языка, чем являются реальными заморочками :)
Нет. Это то, что многие могли бы ожидать по аналогии с уже известными средствами, но при этом работают неожиданно.
Так что — хороший, правильный список.:)
Здравствуйте, race1, Вы писали:
R>Здравствуйте, Курилка, Вы писали:
К>>Программисты из LShift собрали (не очень короткий) список из ньюансов, неожиданностей и неинтуитивных вещей в python.
R>По-моему некоторые "заморочки" весьма странные... Вытекают скорее из незнания основ языка, чем являются реальными заморочками
Здравствуйте, Курилка, Вы писали:
К>>>Программисты из LShift собрали (не очень короткий) список из ньюансов, неожиданностей и неинтуитивных вещей в python. R>>По-моему некоторые "заморочки" весьма странные... Вытекают скорее из незнания основ языка, чем являются реальными заморочками К>Аргументируй?
Inconsistent get interface
I’m often in doubt about the behaviour of get-like methods, due to inconsistent behaviour. Currently some of them raise exception, others just return None. Why None?
>>> {}.get(1)
None
>>> getattr(1, ‘a’)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
AttributeError: ‘int’ object has no attribute ‘a’
>>> getattr(1, ‘a’, None)
None
автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено..
удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None..
Здравствуйте, neFormal, Вы писали:
F>Здравствуйте, Курилка, Вы писали:
К>>Аргументируй?
F>[q] F>Inconsistent get interface
F>I’m often in doubt about the behaviour of get-like methods, due to inconsistent behaviour. Currently some of them raise exception, others just return None. Why None?
F>автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено.. F>удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None..
Может стоит внимательней прочитать, что написано? Как из фразы "Почему None?" следует, что все функции должны возвращать None?
Здравствуйте, Курилка, Вы писали:
F>>автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено.. F>>удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None.. К>Может стоит внимательней прочитать, что написано? Как из фразы "Почему None?" следует, что все функции должны возвращать None?
ну или наоборот, что все должны кидать исключения.. но это ещё больший ахтунг, т.к. код заполонит куча try-catch..
Здравствуйте, neFormal, Вы писали:
F>Здравствуйте, Курилка, Вы писали:
F>>>автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено.. F>>>удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None.. К>>Может стоит внимательней прочитать, что написано? Как из фразы "Почему None?" следует, что все функции должны возвращать None?
F>ну или наоборот, что все должны кидать исключения.. но это ещё больший ахтунг, т.к. код заполонит куча try-catch..
Ну тут нам не хаскель, где есть Maybe, так что или с одной стороны криво, или с другой
Я ждал этого вопроса Посмотреть насколько мои знания Питона соответствуют действительности...
1. Tuples constructor. Constructing tuples is misleading for beginners. For example foo(1,2) is way different than foo((1,2)). On the other hand foo(1) is the same as foo((1)).
Ну это основы, в любой книжке при описании кортежей наверное такое есть — (1) это просто единичка в скобочках, (1,) это кортеж с одним эл-м. А как ещё отличить что-то в просто скобочках, от кортежа?
2. Inconsistent get interface. I’m often in doubt about the behaviour of get-like methods, due to inconsistent behaviour. Currently some of them raise exception, others just return None. Why None?
Ну это так же как {}[1] бросит исключение, а {}.get(1, [default]) вернёт default. В зависимости от ситуации удобнее использовать тот или другой метод. А getattr это вроде вообще для объектов, а не для словарей, там и логика чуть другая. None потому что это по-умолчанию возвращаемое значение
3. Circular imports
Нужно просто не забывать, что Питон — интерпретируемый язык, он выполняет код строчка за строчкой. Поэтому то, что объявлено после import b, и не появится в модуле b — интерпретатор, обрабатывая модуль b, обработал совсем чуть-чуть модуля a.
4. Module naming and side effects
А вот это по-моему реальная засада
5. What do imports import?
Импорт добавляет в текущее пространство имён содержимое импортируемого модуля. А что именно нужно импортировать и что чем является — нужно смотреть в документации модуля который нужно использовать.
6. 999+1 is not 1000
Ну это вообще странно. Как сказано в документации, is проверяет являются ли два объекта на самом деле одним объектом. Т.е. это ни разу не арифметическое сравнение. Вот и получите по голове, если вздумали сравнивать равенство чисел сравнением адресов в памяти, по которым эти числа расположены Это скорее неочевидное поведение человека, делающего 1 is 1
7. The order of unpacking
>>> _, _, _ = 1,2,3
>>> _
3
По-моему очень логично — переменной по-очереди назначаются значения кортежа, и каждое присваивание затирает предыдущее значение. А что было бы лучше, _ == 2, или _ == 1?
On the other hand this syntax is not allowed in function declarations. Strange.
>>> def a(_, _, _): print _
Хо-хо Чего захотели А не желаете ещё что бы Питон вам сам названия переменных и функций придумывал? Что, он такое не умеет? Ах, какое непредсказуемое поведение, оно путает новичков!
Здесь же:
Speaking of function declarations, there’s a nice feature that allows you to define named parameters before unnamed ones, although this syntax works only for function definitions, not for usage:
>>> def foo(a=1, b=2, *args, **kwargs):
… print “a=%r b=%r args=%r kwargs=%r” % (a,b,args,kwargs
…
>>> foo(4,5,6)
a=4 b=5 args=(6,) kwargs={}
>>> foo(a=4, b=5, 6) # I would expect this to work!
File “<stdin>”, line 1
SyntaxError: non-keyword arg after keyword arg
Насколько я знаю, *args и **kwargs это просто соглашение, я не прямое указание "после всех параметров функции можно указать дополнительный кортеж со значениями". Все значения параметров, кроме явно объявленных, а) неименованные параметры помещаются в кортеж args, а все значения б) именованных параметров помещаются в словарик kwargs. Это тоже, должно быть, есть в любой книжке, где есть описание создания функций.
8. Multiline comments are not comments
# This works fine:
if True:
a = 1
#comment
# This fails, though I’d expect it to work:
if True:
a = 1
”’
multiline comment
”’
А что имеется в виду под ”’? Для многострочных коментов есть """ или ''', они прекрасно работают.
9. Finally finally is interesting
Это то, как и должны работать вещи. Потому что по определению finally выполняется [b]всегда[b]. Такая конструкция в яве напечатает в консоль:
Или такой псевдокод тоже должен напечатать в консоль:
function
try
return 1
finally
print('kva')
Сейчас проверил — Питон так и делает. Это уже не основы языка, это основы обработки исключений.
10. List comprehensions, kind of.
List comprehensions contain for keyword. For example this is perfectly normal:
But it’s not possible to use that syntax in a for statement itself:
Опять, чего захотели Питон не умеет варить кофэ? Бе-е-е.
LC, как говорят, "синтаксический сахар" для более удобного создания списка. for это конструкция языка. Почему они должны быть связаны, вообще не понимаю. Потому что и там и там есть слово for?
I have to use ugly workaround:
>>> for x in [k for k in range(3) if k != 2]:
Я бы назвал это обычным кодом, который перебирает список (а, грубо говоря, for только и умеет что перебирать списки), который тут же создаётся с помощью LC. В отличие от настоящего ugly "for x in there and take that and not 2 == x and also check that please".
Вот. Это то что мне показалось "неправильными" заморочками Хотя я знаю Питон далеко не очень хорошо, и изучаю его всего ничего. Вот на StackOverflow там по-моему действительно интересные и малоизвестные штуки — http://stackoverflow.com/questions/101268?sort=votes#sort-top.
Все эти "заморочки" которые выше, описаны наверное в любой книжке про Питон любого уровня, а ещё иногда повторяются в доках на разные либы. Например, вроде в манах на Django, видел упоминание про конструирование кортежей. Хотите писать на новом для себя языке — потрудитесь изучить хотя бы какую-нибудь литературу. Каким бы язык ни был простым — это новый для вас язык.
А ещё, когда непонятно как себя ведёт та или иная конструкция, можно спросить у гугла. Типа python tuples, где по первой ссылке будет рассказано что (1) это не tuple. Или в Питон shell набрать help({}.get) и узнать, что в случае отсутствия ключа исключения не будет. И т.д.
Re: Заморочки в Python
От:
Аноним
Дата:
31.10.09 04:46
Оценка:
Здравствуйте, Курилка, Вы писали:
К>...список из ньюансов, неожиданностей и неинтуитивных вещей в python.
Из самого очевидного: можно маленький вопрос по кортежам?
Что вы ожидаете увидеть в результате выполнения (2+2)*2? Судя по всему (4, 4).
Здравствуйте, neFormal, Вы писали:
К>>Аргументируй?
F>
F>Inconsistent get interface
F>I’m often in doubt about the behaviour of get-like methods, due to inconsistent behaviour. Currently some of them raise exception, others just return None. Why None?
F>
>>>> {}.get(1)
F>None
>>>> getattr(1, ‘a’)
F>Traceback (most recent call last):
F> File “<stdin>”, line 1, in <module>
F>AttributeError: ‘int’ object has no attribute ‘a’
>>>> getattr(1, ‘a’, None)
F>None
F>
F>автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено..
Я что-то не увидел, чтобы автор там хотел именно такого.:)) Значительно больше похоже, что вопрос стоит "а почему у одних get есть второй аргумент — значение по умолчанию (и это правильно), а у других — может отсутствовать (и это неправильно)"?
Там можно так интерпретировать и мне такая интерпретация нравится больше.:)
F>удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None.. :xz:
Может, но это уже другой вариант проверки — если None может быть значением, используй другое умолчание или явно пиши hasattr().
Хотя после Erlang'а мне кажется, что имеет смысл вводить методы, которые сразу возвращают два значения, по типу (hasattr(O,A),getattr(O,A,None)).
Здравствуйте, neFormal, Вы писали:
F>Здравствуйте, Курилка, Вы писали:
F>>>автор хотет чтобы все get-подобные функции возвращали None, если ошибка или чего то не найдено.. F>>>удобство такого подхода понятно, но не всегда это возможно.. с тем же getattr может же быть атрибут 'a' со значением None.. :xz: К>>Может стоит внимательней прочитать, что написано? Как из фразы "Почему None?" следует, что все функции должны возвращать None? :no:
F>ну или наоборот, что все должны кидать исключения.. но это ещё больший ахтунг, т.к. код заполонит куча try-catch..
Вы что-то не так смотрите.
getattr(O,A) — если атрибута нет, кидает исключение
getattr(O,A,D) — если атрибута нет, возвращает D
hasattr(O,A) — проверка наличия атрибута
Dict[A] — если ключа нет, кидает исключение
Dict.get(A,D) — если ключа нет, возвращает D
Dict.has_key(A,D) или D in A — проверка наличия ключа
то есть набор возможностей аккуратно симметричен: кто хочет сразу исключение — может его попросить, кто не хочет — получает значение по умолчанию, а можно просто проверить наличие. Причём всё это в простой форме метода (это по сравнению, например, с Perl, где все такие методы аналогичны get(,None), а чтобы вызвать исключение надо постараться с явной проверкой.) Но есть несимметричность в том, что getattr(O,A) вызывает исключение, а Dict.get(A) — нет (ему явно добавлено None), в то время как было бы логичнее (jIMHO) чтобы Dict.get(A) действовал точно так же как Dict[A], с исключением по отсутствию.
Здравствуйте, netch80, Вы писали:
N>Но есть несимметричность в том, что getattr(O,A) вызывает исключение, а Dict.get(A) — нет (ему явно добавлено None), в то время как было бы логичнее (jIMHO) чтобы Dict.get(A) действовал точно так же как Dict[A], с исключением по отсутствию.
о чём я и сказал — это ахтунг.. если я захочу исключение, я дёрну Dict[A], но обычно я очень не хочу исключений..
а добиваться симметричности в поведении функций, основываясь только на их названии это очень оригинально.. может ещё в какой нить PEP ввести требование, чтобы функции начинающиеся с get в случае некорректного возвращенаемого значения кидали исключение?.
Здравствуйте, Курилка, Вы писали:
К>Программисты из LShift собрали (не очень короткий) список из ньюансов, неожиданностей и неинтуитивных вещей в python.
Самые неприятные вещи там связаны с привязкой переменных. Желающие могут предсказать вывод этого:
x = 1
print(x)
y = sum(x for x in range(10))
print(x)
z = sum([x for x in range(20)])
print(x)
И этого: x += y и x = x + y — одно и то же?
def eq_plus(a):
a = a + a
def plus_eq(a):
a += a
a = [1]
eq_plus(a)
print(a)
plus_eq(a)
print(a)
Здравствуйте, race1, Вы писали:
R>2. Inconsistent get interface. I’m often in doubt about the behaviour of get-like methods, due to inconsistent behaviour. Currently some of them raise exception, others just return None. Why None? R>Ну это так же как {}[1] бросит исключение, а {}.get(1, [default]) вернёт default. В зависимости от ситуации удобнее использовать тот или другой метод. А getattr это вроде вообще для объектов, а не для словарей, там и логика чуть другая.
нет, getattr есть у всех.. даже у int-ов..
R>8. Multiline comments are not comments R>А что имеется в виду под ”’? Для многострочных коментов есть """ или ''', они прекрасно работают.
докстринги(а ведь это к ним отсылка) использовать в качестве комментов несколько странно..
R>9. Finally finally is interesting R>Это то, как и должны работать вещи. Потому что по определению finally выполняется [b]всегда[b]. Такая конструкция в яве напечатает в консоль: R>Сейчас проверил — Питон так и делает. Это уже не основы языка, это основы обработки исключений.
и в finally заходит обязательно перед выходом из блока except.. например, при return/raise из except, но те же конструкции в finally сильнее..
Здравствуйте, neFormal, Вы писали:
F>Здравствуйте, netch80, Вы писали:
N>>Но есть несимметричность в том, что getattr(O,A) вызывает исключение, а Dict.get(A) — нет (ему явно добавлено None), в то время как было бы логичнее (jIMHO) чтобы Dict.get(A) действовал точно так же как Dict[A], с исключением по отсутствию.
F>о чём я и сказал — это ахтунг.. если я захочу исключение, я дёрну Dict[A], но обычно я очень не хочу исключений..
Странные задачи, однако.:) Я, наоборот, стараюсь делать так, чтобы исключения вылетали по любой непредусмотренной ситуации, а только если я твёрдо уверен, что они не нужны — делать замену (get с дефолтом).
F>а добиваться симметричности в поведении функций, основываясь только на их названии это очень оригинально..
А что тут "оригинального"? По-моему, это как раз общее место: одинаковое должно называться одинаково. Вы же не хотите, чтобы destroy() создавал объект, а contstruct() разрушал? Да, это крайний пример, в реальности не встречающийся. Но когда одно и то же действие в разных местах называется add, append, push или extend, это просто задалбывает.
F> может ещё в какой нить PEP ввести требование, чтобы функции начинающиеся с get в случае некорректного возвращенаемого значения кидали исключение?.
Если уточнить "при отсутствии значения по умолчанию в аргументах функции" — я только "за".
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Курилка, Вы писали:
К>>...список из ньюансов, неожиданностей и неинтуитивных вещей в python.
А>Из самого очевидного: можно маленький вопрос по кортежам? А>Что вы ожидаете увидеть в результате выполнения (2+2)*2? Судя по всему (4, 4).
Здравствуйте, netch80, Вы писали:
N>>>Но есть несимметричность в том, что getattr(O,A) вызывает исключение, а Dict.get(A) — нет (ему явно добавлено None), в то время как было бы логичнее (jIMHO) чтобы Dict.get(A) действовал точно так же как Dict[A], с исключением по отсутствию. F>>о чём я и сказал — это ахтунг.. если я захочу исключение, я дёрну Dict[A], но обычно я очень не хочу исключений.. N>Странные задачи, однако. Я, наоборот, стараюсь делать так, чтобы исключения вылетали по любой непредусмотренной ситуации, а только если я твёрдо уверен, что они не нужны — делать замену (get с дефолтом).
я так понимаю, что функции у тебя обычно начинается с try?.
F>>а добиваться симметричности в поведении функций, основываясь только на их названии это очень оригинально.. N>А что тут "оригинального"? По-моему, это как раз общее место: одинаковое должно называться одинаково.
только dict.get() и getattr() делают немного разные вещи.. первый возвращает дефолтное значение, и правильней было бы его назвать dict.get_or_default()..
F>> может ещё в какой нить PEP ввести требование, чтобы функции начинающиеся с get в случае некорректного возвращенаемого значения кидали исключение?. N>Если уточнить "при отсутствии значения по умолчанию в аргументах функции" — я только "за".
угу.. get_object() вернёт либо объект, либо кинет исключение, если мембер == None.. только нафига исключение?.
Здравствуйте, neFormal, Вы писали:
N>>>>Но есть несимметричность в том, что getattr(O,A) вызывает исключение, а Dict.get(A) — нет (ему явно добавлено None), в то время как было бы логичнее (jIMHO) чтобы Dict.get(A) действовал точно так же как Dict[A], с исключением по отсутствию. F>>>о чём я и сказал — это ахтунг.. если я захочу исключение, я дёрну Dict[A], но обычно я очень не хочу исключений.. N>>Странные задачи, однако.:) Я, наоборот, стараюсь делать так, чтобы исключения вылетали по любой непредусмотренной ситуации, а только если я твёрдо уверен, что они не нужны — делать замену (get с дефолтом). F>я так понимаю, что функции у тебя обычно начинается с try?. :)
Откуда такие странные предположения? Нет, конечно. try-catch стоят в строго определённых местах (очистные операции, движок событий, вызовы коллбэков).
F>>>а добиваться симметричности в поведении функций, основываясь только на их названии это очень оригинально.. N>>А что тут "оригинального"? По-моему, это как раз общее место: одинаковое должно называться одинаково. F>только dict.get() и getattr() делают немного разные вещи.. первый возвращает дефолтное значение, и правильней было бы его назвать dict.get_or_default()..
Неверно говоришь. dict.get() делает то же, что трёхаргументный getattr(), но не то же, что двухаргументный getattr().
F>>> может ещё в какой нить PEP ввести требование, чтобы функции начинающиеся с get в случае некорректного возвращенаемого значения кидали исключение?. N>>Если уточнить "при отсутствии значения по умолчанию в аргументах функции" — я только "за". F>угу.. get_object() вернёт либо объект, либо кинет исключение, если мембер == None.. только нафига исключение?.
Затем же, зачем вообще придумали исключения. Как ты думаешь, для чего их придумали вместо передачи всех кодов ошибки сразу? ;))
Здравствуйте, netch80, Вы писали:
F>>угу.. get_object() вернёт либо объект, либо кинет исключение, если мембер == None.. только нафига исключение?. N>Затем же, зачем вообще придумали исключения. Как ты думаешь, для чего их придумали вместо передачи всех кодов ошибки сразу? )