LINUX.ORG.RU
Ответ на: комментарий от ero-sennin

>Ошибся, с кем не бывает. :)

оговорочки по фрейду рулят :) Питон, кстати, тоже рулит

geek ★★★
()

там блин и так уже понаобсуждали, куда еще-то в топ10 попасть хотите?

anonymous
()

К вопросу о виртуальных атрибутах (foo=) в Руби:
в Питоне, если сильно хочется, подобное делается
за пять минут:

class DynamicAttributes:
    def _handler(self, name, type):
        if not name.startswith(type):
            return getattr(self, '%s_%s' % (type, name))
        else:
            raise AttributeError(name)
    def __getattr__(self, name):
        return self._handler(name, 'get')()
    def __setattr__(self, name, value):
        try:
            self._handler(name, 'set')(value)
        except AttributeError:
            self.__dict__[name] = value


Вышеприведённый код позволяет делать так:
class Test(DynamicAttributes):
    def get_foo(self):
        return 'this is foo'
    def set_foo(self, value):
        print 'foo =', value

После этого все объекты класса Test будут иметь атрибут 'foo':
t = Test()
print t.foo
t.foo = '12'

Короче, с помощью __getattr__, __setattr__ и __delattr__
программист на Питоне имеет возможность воплотить свои самые 
извращённые мечты. А Руби нервно курит под стулом. 8)

ero-sennin ★★
() автор топика

К вопросу о доступе к атрибутам класса через @ (Ruby) или self (Python):
а кто не даёт в Питоне сделать так:

class a:
    def print_foo(s)
        print s.foo

s., конечно, вдвое длиннее чем @, но идею вы поняли. =)
С другой стороны, использование self позволяет избежать
лишнего синтаксического мусора и напоминает программеру,
что при вызове метода класса в качестве первого параметра
всегда передаётся объект-владелец метода.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

>s., конечно, вдвое длиннее чем @, но идею вы поняли

Не в двое - т.к. "@" с шифтом жмётся и пальцы далеко убегают. Однако, делая так, я уже пару раз попадался на желании использовать временную переменную с тем же именем "s" (чаще всего s=os.stat(...)) - такую ошибку потом очень интересно ловить:-)

DonkeyHot ★★★★★
()
Ответ на: комментарий от ero-sennin

Ну это монятно что извратиться можно, в руби есть похожие механизмы, только я пока их не сильно смотрел, т.к. не особо нужны. К тому же всё таки намного приятенее писать

def x=(x)

def +(b) def -(c)

чем питоновские изварты.

def __sub__

def __div__

но вообще конечно синтаксис далеко не решающий фактор, хотя приятнее коенчно код читать.

CrazyPit ★★★
()
Ответ на: комментарий от ero-sennin

Во первых @ писать нужно только перед обращением к свойству (а оно часто обёрнуто get/set'ром, а перед вызовом метода не надо. Во вторых пиша s. ты нарушаешь правило наименьшей неожиданность (что в данном случае очень плохо), но это фигня ведь можно сделать abbrev (а уменя так и сделано, что s будет приваращаться в self., меня больше раздражает что его нужно указывать в параметрах раз. Во воторых код хуже читатеться (и не красивый какой-то) когда в нём куча self.

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

> в руби есть похожие механизмы, только я пока их не сильно смотрел

А где про них почитать?

ero-sennin ★★
() автор топика
Ответ на: комментарий от CrazyPit

Ещё вопрос появился, по поводу свойств в Руби.
Имеем такой код:

class Foo
    def foo
        'this is a foo'
    end
end

foo = Foo.new
puts foo.foo

Получаем, естественно, 'this is a foo'.
А как получить не значение функции, а саму функцию foo?

ero-sennin ★★
() автор топика
Ответ на: комментарий от kosmonavt

> m = foo.method("foo")

М-да, не сказал бы я, что это красиво. Видимо, это плата за перегрузку foo= и возможность вызывать функции без скобок. =)

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

Но заметь вызов функции без скобок юзаеться намного чаще чем получение функции как foo.bar вместо foo.method("foo") :)

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

> Но заметь вызов функции без скобок юзаеться намного чаще чем получение функции как foo.bar вместо foo.method("foo") :)

Может быть. С другой стороны, обязательные скобки при вызове функции позволяют с первого взгляда отличать функции от переменных.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

>Если не не можешь жить без анонимных функций, то и пиши себе на Хаскеле.

Наооборот меня в питоне убивает недолямбда, анон. функции всё таки иногда нужны.

CrazyPit ★★★
()
Ответ на: комментарий от ero-sennin

> обязательные скобки при вызове функции позволяют с первого взгляда отличать функции от переменных

Если не использовать свойства с get/set. Тогда границы существенно размываются :)

watashiwa_daredeska ★★★★
()

Субъективное МХО. Питона не любитель. Хотя десять лет назад был бы в диком восторге от его синтакиса (как раз вынашивал мысли об учёте отсутпов компиллятором). Но и против ничего не имею. И, похоже, у этого языка очень большое будущее.

Руби - не знаю. То, что видел, вызывает отторжение. Не смотря на всю рекламную шумиху, не считаю, что у него есть шанс откусить приличный сегмент рынка.

KRoN73 ★★★★★
()
Ответ на: комментарий от CrazyPit

> Наооборот меня в питоне убивает недолямбда

Гвидо справедливо рассудил, что любой функции, состоящей более чем из одной строчки, стоит дать понятное имя. Тогда читателям кода будет легче понять, что эта функция делает. Но для особых фанатов ФП он таки сделал эту простенькую лямбду, хотя и никогда не рекомендовал ей пользоваться.

Кроме того, было замечено, что люди в большинстве случаев пользуются лямбда-функциями в сочетании с функциями map или filter, например map(lambda x: x**2, filter(lambda x: x<3, [1,2,3])). Поэтому в Питоне-2.0 появилось конструирование списков (list comprehensions): [x**2 for x in [1,2,3] if x<3]. В Руби таких штук я не замечал. :P

ero-sennin ★★
() автор топика
Ответ на: комментарий от watashiwa_daredeska

> Если не использовать свойства с get/set.
> Тогда границы существенно размываются :)

Размытие границ между функциями и переменными уместно
в чисто функциональных языках, где значение функции
полностью определяется её параметрами. Руби к чисто
функциональным языкам не относится, и последовательные
вызовы функций могут давать разные значения. Например:

class Foo
    def initialize
        @n = 0
    end
    def bar
        @n += 1
    end
end

foo = Foo.new
puts foo.bar
puts foo.bar

При выполнении этого кода получим:
1
2

Мораль ясна? Фундаментальное отличие между переменными
и функциями в том, что переменные сохраняют свои значения,
а функции - нет (за исключением, разве что, многопоточных
программ). А если при отладке кода переменные
у меня вдруг начнут самопроизвольно менять значения,
я решу, что свихнулся нафиг, и уйду пить горькую вотку. =)

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

>Гвидо справедливо рассудил, что любой функции, состоящей более чем из одной строчки, стоит дать понятное имя. Тогда читателям кода будет легче понять, что эта функция делает. Но для особых фанатов ФП он таки сделал эту простенькую лямбду, хотя и никогда не рекомендовал ей пользоваться.

Еслиб в питоне можно было нормально конструкции в одну строку писать...

> Кроме того, было замечено, что люди в большинстве случаев пользуются лямбда-функциями в сочетании с функциями map или filter, например map(lambda x: x**2, filter(lambda x: x<3, [1,2,3])). Поэтому в Питоне-2.0 появилось конструирование списков (list comprehensions): [x**2 for x in [1,2,3] if x<3]. В Руби таких штук я не замечал. :P

Здесь я согласен list comprehensions более красиво выглядит, в руби с той же смысловой нагрузкой можно написать:

[1,2,3].map_reject{|x| x**2 if x <3}

видишь лексем столько же.

class Array def map_reject (self.collect{|x| yield x}).reject{ |x| x.nil?} end end

Хотя если for-ов больше одного...

Но вообще в таких случаях и руби и питон впролёте Common Lisp Loop намного круче;)

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

Кстати в питоне через зад можно обявлять методы в другом месте от основного класса, а в руби всё очень красиво.

CrazyPit ★★★
()
Ответ на: комментарий от ero-sennin

Не надуманный пример, если кто в геттер деструктивный сделает, да ещё с деструкией того же параметра (хотя наверное кое-где такое пригодиться, но в очень редких случаях) то ССЗБ, если так думать то можно и все операторы у стандартных типов перегрузить -- вообще весело будет:)

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

> Кстати в питоне через зад можно обявлять методы в другом месте от основного класса

Не совсем понял, что имеется в виду. =)

ero-sennin ★★
() автор топика
Ответ на: комментарий от CrazyPit

> Еслиб в питоне можно было нормально конструкции в одну строку писать...

Правильно, нельзя, ибо писать конструкции в одну строку - зло. :-E

ero-sennin ★★
() автор топика
Ответ на: комментарий от CrazyPit

> если кто в геттер деструктивный сделает, да ещё с деструкией того же параметра (хотя наверное кое-где такое пригодиться, но в очень редких случаях) то ССЗБ

Пример, понятное дело, искусственный, но таки согласитесь, что функции и переменные в ООП фундаментально различные сущности. :)

ero-sennin ★★
() автор топика
Ответ на: комментарий от ebuilder

> В ООП нет понятия переменных. И тем более там нет понятия функций.

Вот этого не надо =) Даже в Smalltalk были instance _variables_. И в питоновской документации параллельно используются термины method и member function, data и member variable.

Вообще, давайте не придираться к терминам, а спорить по существу.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

Python:

class foo:
    def bla(self):
        return 10


class foo:
    def tla(self):
        return 10

a = foo()

print a.tla()

print a.bla()
---
Ошибка:
Traceback (most recent call last):
  File "<stdin>", line 16, in ?
AttributeError: foo instance has no attribute 'bla'
class Foo
  def bla()
       10
  end
end


class Foo
  def tla()
      12
  end
end

a = Foo.new

puts a.tla

puts a.bla

---

12
10

вот про что я

CrazyPit ★★★
()
Ответ на: комментарий от CrazyPit

Понял. Но не могу сказать, что определять класс по частям в пяти разных местах - это красиво. Представьте себе: человек видит только последнее объявление, и недоумевает, откуда взялись все остальные члены класса.

А в приведённом питоновском примере есть простая логика. Когда вы описываете класс foo, вы создаёте объект типа classobj, и ссылку на него с именем foo. Когда вы описываете его второй раз, вы создаёте второй объект типа classobj и ссылку на него, с тем же именем foo. При этом ссылка на первый объект уничтожается, а следовательно, уничтожается и сам объект.

ero-sennin ★★
() автор топика
Ответ на: комментарий от CrazyPit

Забыл написать. Изменить уже определённый класс в Питоне можно. :)

class Foo:
    def bla(self):
        return 10

def tla(self):
    return 12

Foo.tla = tla

При этом отчётливо видно, что происходит не создание
нового класса, а изменение существующего.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

Нужна такая фишка для добавления функций в библиотечный класс, в моём примере добавлялся новый итератор в класс Array, в питоне согласен тоже самое, но не так красиво. И если добавляешь несколько функций то не надо каждый раз писать Foo.tla=tla

CrazyPit ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.