LINUX.ORG.RU

[python]Определить новый метод в импортированном модуле.

 


0

0

Итак, есть модуль pysvn, в нём есть класс Client и его метод log(), который позволяет извечь некоторую информацию о коммите. Я хочу определить метод Client.author(), который будет возвращать строку-имя пользователя. Если просто написать

class Client:
    def author(self, repository_url, revision):
        return self.log(repository_url, revision_start=revision, revision_end=revision)[0]['author']
# Запрашиваем информацию по ревизии revision из репозитария по ссылке, получаем в ответ список с единственным элементом-словарём, поле 'author' в котором содержит имя автора. 

То при попытке использования этого метода client.author(myRepoURL, myRevision) получим

AttributeError: author

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

Как в python'е добавить к классу из загружаемого модуля метод?

★★★★★
Ответ на: комментарий от www_linux_org_ru

Да вот что то не видно на Питоне таких библиотек... Насчёт кодеров отчасти согласен. Вот только как определить грань эзотеричности? Для кого то (прямо скажем, для многих) лямбды, карринг, вообще функции высшего порядка - чистая эзотерика. Как быть?

Hjorn
()
Ответ на: комментарий от dccp

> Люди, обычно, решают реальные задачи наиболее безопасным, простым и поддерживаемым способом.

Обычно да. Но есть случаи, когда нужно необычно. Хотя бы просто чтобы избежать лишнего boilerplate кода. В тикле приёмы, обсуждаемые выше, используются в полный рост и с большой пользой. В перле тоже много интересного можно сделать, задействуя dynamic scoping и source filters. Даже руби неплохо приспособили для некой вариации метапрограммирования. Может это действительно не нужно и вредно, а я просто красноглазый гик. Но блин, посмотришь как джависты жонглируют объектами и молятся на паттерны - тошно становится. От динамических языков хочется нечто большего, а не всё как обычно + отсутствие поддержки компилятора + тормоза.

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

> Да вот что то не видно на Питоне таких библиотек... Насчёт кодеров отчасти согласен. Вот только как определить грань эзотеричности? Для кого то (прямо скажем, для многих) лямбды, карринг, вообще функции высшего порядка - чистая эзотерика. Как быть?

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

*лично* мой ответ на вопрос "Как быть?" -- сделать хороший язык программирования, а до этого *хотя бы* озвучить для себя (и других) свои требования к нему.

Что же касается конкретных вопросов -- имхо:

1. анонимные функции полезны (и обязательны даже для кодеров), т.к. проясняют намерения программиста

2. карринг синтаксически более вреден, чем полезен

3. функции высшего порядка писать должны в основном "библиотекари", а юзать могут все.

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

> Но блин, посмотришь как джависты жонглируют объектами и молятся на паттерны - тошно становится.

Я подозреваю, что знание любых паттернов не поможет написать на яве функцию T max(T a, T b), которая бы работала для любых T, имплементирующих интерфейс MyComparable. Но поклясться не могу :-)

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

> *лично* мой ответ на вопрос "Как быть?" -- сделать хороший язык программирования

Я имел ввиду, что трудно определить, какие возможности языка являются эзотерическими. Это сильно зависит от способа мышления и квалификации программиста. Тут я придерживаюсь простого правила: если не понимаешь, зачем нужна какая то фича, значит она тебе не нужна. Когда то может прийдёт понимание. Позже прийдёт понимание о пределах применимости этой фичи :) Искусственно кого то ограничивать неправильно, imho. Ну разве что в таких вещах, как coding style.

Насчёт сделать хороший язык: и так уж наплодили всяких :) Всё ж таки кажется, что лучший вариант - это очень гибкий и мощный базовый язык + DSL'и на его основе. Но что то лисп не прижился в мейнстриме.

Hjorn
()
Ответ на: комментарий от www_linux_org_ru

> там приходится писать f(......, void g(void*), void* g_parameter)

Ну где тут замыкания? С каких это пор открытый список параметров оказался = замыканиям?

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

Функция f принимает на вход именно замыкание, которое, из-за невозможности записать его как один аргумент, записывается как два: g и g_parameter

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

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

Ты точно понимаешь, что такое замыкание?

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

Ты точно понимаешь, что такое замыкание?

Рассмотри два куска кода, первый на «С с замыканиями», второй на обычном С.

 
void f(int, void g(double));
void h(double, int);

void sample(int* i)
{
  void g(double x) { .... h(x, *i) .... } /* g -- бесспорно замыкание */
  f(123, g);
}
 
void f(int, void g(double, void*), void* g_parm);
void h(double, int);
void g(double x, int* i) { .... h(x, *i) .... }

void sample(int* i)
{
  f(123, g, i); /* здесь то же самое замыкание -- это пара (g,i) */
}

Понятно, что во втором случае термин «замыкание» используется с точность до какого-то изоморфизма, это изоморфизм надо определить, потом доказать, ... но мне это лень...

... но если кто-то укажет мне на ошибку, будет интересно.

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

Замыкание - это доступ из контекста функии к свободным переменным.

Ты тут везде демонстрируешь передачу через параметры.

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

Получается "замыкание вручную". Порой полезно, но неудобно. Да и замыканием трудно это назвать. Вернуть то его из функции нельзя, и не first class citizen совсем. Вот плюсовый функтор больше похож на замыкание.

Hjorn
()
Ответ на: комментарий от LamerOk

> Замыкание - это доступ из контекста функии к свободным переменным. Ты тут везде демонстрируешь передачу через параметры.

Вероятно, ты читал про замыкание в русской википедии. Иди читай английскую.

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

> Получается "замыкание вручную". Порой полезно, но неудобно. Да и замыканием трудно это назвать. Вернуть то его из функции нельзя, и не first class citizen совсем. Вот плюсовый функтор больше похож на замыкание.

Ну дык в С всегда закат солнца вручную.

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

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

> Всё ж таки кажется, что лучший вариант - это очень гибкий и мощный базовый язык + DSL'и на его основе.

Только так. Даже точнее embedded DSL.

> Но что то лисп не прижился в мейнстриме.

Ну так динамически типизированный же. И не мог прижиться.

Сложнее сказать, почему не прижились boo & nemerle.

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

Это да, это огорчительный нюанс. Хотя вот в руби тоже надо делать f.call, а в перле $f->(), по сути та же ситуация. Плюсам и перлу простительно, а вот руби я этого не прощу ;)

Hjorn
()
Ответ на: комментарий от www_linux_org_ru

> Но что то лисп не прижился в мейнстриме.

> Ну так динамически типизированный же. И не мог прижиться.

Так лисперы вроде хвалятся, что можно прикрутить статическую типизацию на раз-два. Или это всё ерунда? Надо бы перечитать "Фразу о Лиспе".

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

> Так лисперы вроде хвалятся, что можно прикрутить статическую типизацию на раз-два. Или это всё ерунда? Надо бы перечитать "Фразу о Лиспе".

Даже если и можно, никто под нее не пишет. И это не так просто, как может показаться.

Рассмотри хотя бы void* f( void*, void* g(void*, void*), void*) и выясни, которые из void* должны совпадать. Это требует работы.

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

> Так лисперы вроде хвалятся, что можно прикрутить статическую типизацию на раз-два. Или это всё ерунда? Надо бы перечитать "Фразу о Лиспе".

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

Так что, вероятно, ерунда.

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

> Так лисперы вроде хвалятся, что можно прикрутить статическую типизацию на раз-два. Или это всё ерунда? Надо бы перечитать "Фразу о Лиспе".

На глаз кажется, что большую кода можно типизировать вручную/полуавтоматически ... но вопрос -- до какой степени? Вот например один чувак придумал дополнительную типизацию для ... ЕМНИП многонитевых программ, и типизируя вручную сишный исходник перла, отловил 2 явных бага. Вот так.

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

> Вероятно, ты читал про замыкание в русской википедии. Иди читай английскую.

Не читал ни там, ни там, но сходил и туда, и туда. Специально для тебя цитата с английской:

In computer science, a closure is a first-class function with free variables that are bound by the lexical environment.

In computer programming, a free variable is a variable referred to in a function that is not a local variable or an argument of that function[1].

Тебе "argument of that function" перевести?

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

Тебе «argument of that function» перевести?

«that function» в данном случае это g, а не f. Для g переменная i является свободной и связывается функцией sample.

З.Ы. скучно...

void f(int, void g(double));
void h(double, int);

void sample(int* i)
{
  void g(double x) { .... h(x, *i) .... } /* g -- замыкание */
  f(123, g);
}
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Для g переменная i является свободной и связывается функцией sample.

И что? Какое отношение поодержка замыканий в гнусных вложенных функциях и имеют к обращению через указатель, которое ты столь упорно демонстрируешь? Если ты передал сам указатель через замыкание, это совсем не значит, что ты замкнул ту переменную, на которую он указывает.

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

> Если ты передал сам указатель через замыкание, это совсем не значит, что ты замкнул ту переменную, на которую он указывает.

1. Это вопрос отнюдь не однозначный.

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru
void f(int, void g(double));
void h(double, int);

void sample(int i)
{
  void g(double x) { .... h(x, i) .... } /* g -- замыкание */
  f(123, g);
}
void f(int, void g(double, void*), void* g_parm);
void h(double, int);
void g(double x, void* j) { .... h(x, (int)j) .... }

void sample(int i)
{
  f(123, g, (void*)i); /* здесь то же самое замыкание -- пара (g,i) */
}

Реально так конечно никто делать не будет ( sizeof(int) м.б. != sizeof(void*) )

Я так написал только чтобы ты отстал с указателями.

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

Это вопрос отнюдь не однозначный.

Да нет, как раз этот вопрос абсолютно однозначен.

Реально так конечно никто делать не будет ( sizeof(int) м.б. != sizeof(void*) )

Реально как раз именно так и делают и в хвост, и в гриву, лол.

Я никак не могу понять, где ты вот в этом фрагменте:

void f(int, void g(double, void*), void* g_parm);
void h(double, int);
void g(double x, void* j) { .... h(x, (int)j) .... }

void sample(int i)
{
  f(123, g, (void*)i); /* здесь то же самое замыкание -- пара (g,i) */
}
замыкание нашел? В предыдущем оно хотя бы есть применительно к i. А тут - обычная передача указателей.

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

> где ты вот в этом фрагменте: замыкание нашел? В предыдущем оно хотя бы есть применительно к i. А тут - обычная передача указателей.

Если быть точным, то тут имеется изоморфизм, при котором пара (g,i) переводится в замыкание. А математики не различают изоморфные объекты.

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

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

Ни чего оно никуда не переводится, "математик". ))) Есть такая вещь, как арифметика указателей. Намек понял? Указатели не изоморфны замыканиям.

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

В последнем примере указатели вообще не используются [а void* стоит только потому, что обычно нужен именно он, можно и его заменить на int]

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

Что значит "не используются"? А это что?

f(int, void g(double, void*), void* g_parm);

Я вижу тут целое и два указателя - на функцию и обобщенный.

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

и не видишь, что реально используется int.

void f(int, void g(double, int), int g_parm);
void h(double, int);
void g(double x, int i) { .... h(x, i) .... }

void sample(int i)
{
  f(123, g, i); /* здесь то же самое замыкание -- пара (g,i) */
}
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

Так ты опять поменял фрагмент с указателями, на фрагмент с унылой передачей параметров. ))) И что самое смешное - в этом куске нет никаких замыканий. ))))

Здесь нет обращения из тела функции к переменным, объявленным вне её. Тебе точно нужно подтянуть понимание "замыкания", чтобы не выдвигать утверждений об использовании замыканий в libcurl. )))

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

> Здесь нет обращения из тела функции к переменным, объявленным вне её. Тебе точно нужно подтянуть понимание "замыкания", чтобы не выдвигать утверждений об использовании замыканий в libcurl. )))

Спасибо За Бесценное Наставление, О Великий Гуру.

Попытки объяснить тебе, почему вызов функции из libcurl можно (с точностью до изоморфизма) назвать замыканием, закончились неудачей. Ну да ладно.

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