Domyślam się, że pewnie trzeba edytować obiekt String - czy tak się on
nazywa? I jak wtedy należy zadeklarować funkcję i skąd wziąć ten str
znajdujący się "przed kropką"?
Chodzi mnie o mniej więcej takie coś:
"string".jakasfunkcja() - NIE jakasfunkcja("string")
Czy wie ktoś jak coś takiego zrobić?
Można tak ...
>>> class bla(type("sss")):
... def fun(self): print "jestem",self
...
>>> bla("sss")
'sss'
>>> bla("sss").fun()
jestem sss
>>>
Tylko po co?
p. m.
> Aa można bez bla("sss")? Samo "sss".fun()?
Pisanie obiektowe nie polega na zmienianiu wszystkiego na klasy i metody.
A takie "uzdatnianie" typow wbudowanych to chyba nie jest najlepszy
pomysl.
w Ruby jest to mozliwe i sprawdza sie calkiem dobrze
pzdr
szeryf
--
Przemysław ,,Szeryf'' Kowalczyk :: http://szeryf.wordpress.com/
>>> Aa można bez bla("sss")? Samo "sss".fun()?
>>
>> Pisanie obiektowe nie polega na zmienianiu wszystkiego na klasy i metody.
>> A takie "uzdatnianie" typow wbudowanych to chyba nie jest najlepszy
>> pomysl.
>
> w Ruby jest to mozliwe i sprawdza sie calkiem dobrze
Zdania na ten temat są podzielone.
GS
--
Grzegorz Staniak <gstaniak _at_ wp [dot] pl>
...w szczegolnosci na grupie pythonowej :)
> Czyli mówisz, że lepszym rozwiązaniem byłoby użycie fun("aaa")
> anieżeli "aaa".fun(), mam rację?
Pomijając czy lepszym czy gorszym - użycie fun("aaa") jest jedynym :).
Poza tym lepszym - głupio wywoływać metodę obiektu który tejże metody nie
posiada :)
p. m.
> Czyli mówisz, że lepszym rozwiązaniem byłoby użycie fun("aaa")
> anieżeli "aaa".fun(), mam rację?
W Pythonie string (czyli typ o nazwie `str` [1]_) jest typem
wbudowanym. Oznacza to, że jest wyposażony w pewną ograniczoną
liczbę metod [2]_ (czyli funkcji, które można wywoływać w sposób
nazwa_obiektu.funkcja()).
Jeśli mowa o metodzie `replace`, to obiekt typu `str` już taką
posiada:
>>> s = 'sss'
>>> type(s)
<type 'str'>
>>> type(s.replace)
<type 'builtin_function_or_method'>
a zmiana stringa (a dokładniej utworzenie nowego obiektu
typu `str` z nową zawartością [3]_) wygląda tak:
>>> s = 'sss'
>>> s
'sss'
>>> s = s.replace('s', 'b')
>>> s
'bbb'
Gdy chcesz wykonać jakąś akcję na obiekcie typu `str`,
której nie realizuje żadna z wbudowanych metod, to masz
dwa wyjścia:
1. tworzysz oddzielną funkcję i przekazujesz jej obiekt
typu `str`:
>>> import string
>>> def liczba_duzych_liter(s):
... return len([c for c in s if c in string.ascii_uppercase])
...
>>> s = 'Ala ma kota'
>>> liczba_duzych_liter(s)
1
>>> liczba_duzych_liter('Ala ma Asa')
2
2. rozszerzasz obiekt wbudowany (dziedziczysz po klasie `str`) i dodajesz
metodę, której Ci brakuje:
>>> class LiczDuzeLiteryStr(str):
... def __init__(self, s):
... str.__init__(self, s)
... self.s = s
... def liczba_duzych_liter(self):
... return len([c for c in self.s if c in string.ascii_uppercase])
...
>>> s = LiczDuzeLiteryStr('Ala ma kota')
>>> s
'Ala ma kota'
>>> s.liczba_duzych_liter()
1
>>> s = LiczDuzeLiteryStr('Ala ma Asa')
>>> s
'Ala ma Asa'
>>> s.liczba_duzych_liter()
2
Który sposób wybrać zależy tylko i wyłącznie od sytuacji
i Twoich potrzeb. Nie ma tu żadnego religijnego nakazu
stosowania tej czy innej metody.
W praktyce jednak nie pamiętam, abym kiedykolwiek
potrzebował rozszerzać typ `str`. Raczej wybieram
zwykłą funkcję.
To, że w Pythonie wszystko jest obiektem nie oznacza,
że nie należy używać funkcji. Python to na szczęście
nie Java.
.. [1] http://docs.python.org/lib/typesseq.html
.. [2] http://docs.python.org/lib/string-methods.html
.. [3] http://docs.python.org/ref/types.html
RW
>>>>> Aa można bez bla("sss")? Samo "sss".fun()?
>>>>
>>>> Pisanie obiektowe nie polega na zmienianiu wszystkiego na klasy i
>>>> metody.
>>>> A takie "uzdatnianie" typow wbudowanych to chyba nie jest najlepszy
>>>> pomysl.
>>>
>>> w Ruby jest to mozliwe i sprawdza sie calkiem dobrze
>>
>> Zdania na ten temat są podzielone.
>
> ...w szczegolnosci na grupie pythonowej :)
Pewnie masz trochę racji, aczkolwiek nie do końca - czytałem też programistów
Javy którzy nie byli zachwyceni pomysłem modyfikowania wbudowanych typów. Ze
strony deweloperów Pythona najlepszy komentarz to słowo "monkeypatching"
używane do opisania tego zjawiska. Osobiście uważam, że zaleta to żadna,
a upierdliwość dla utrzymujących kod znaczna. A już karalne powinno być tego
typu zachowanie w bibliotekach - włączasz sobie bibliotekę X i nagle typy
wbudowane zaczynają mieć inną semantykę.
> w Pythonie można to zrobić tak:
> "abc".replace("b", "s")
> I taki sposób jest moim zdaniem najlepszy. I teraz pytanie. Jak coś
> takiego zrobić? Pierwszą funkcję jest dla mnie łatwo zdefiniować.
> Problem jest tylko z "abc".replace("b", "s").
>
> Domyślam się, że pewnie trzeba edytować obiekt String - czy tak się on
> nazywa? jak wtedy należy zadeklarować funkcję i skąd wziąć ten str
> znajdujący się "przed kropką"?
> Chodzi mnie o mniej więcej takie coś:
> "string".jakasfunkcja() - NIE jakasfunkcja("string")
W Pythonie to jest niemożliwe, bo klas wbudowanych str czy int nie można
zmieniać. No chyba, że stworzysz swoją klasę dziedziczącą po str i tam
powsadzasz swoje metody. Ale i tak nie będzie możliwe uzyskanie efektu
"bezpośredni string".moja_metoda().
Z kolei uzyskanie takiego efektu w Ruby jest trywialne.
--
Jarosław Zabiełło
http://blog.zabiello.com
lopex
>> Pewnie masz trochę racji, aczkolwiek nie do końca - czytałem też programistów
>> Javy którzy nie byli zachwyceni pomysłem modyfikowania wbudowanych typów. Ze
>> strony deweloperów Pythona najlepszy komentarz to słowo "monkeypatching"
>> używane do opisania tego zjawiska. Osobiście uważam, że zaleta to żadna,
>> a upierdliwość dla utrzymujących kod znaczna. A już karalne powinno być tego
>> typu zachowanie w bibliotekach - włączasz sobie bibliotekę X i nagle typy
>> wbudowane zaczynają mieć inną semantykę.
>>
> Dlatego w Ruby 2.0 pojawić się ma selector namespace, czyli ograniczenie
> takich zmian do modułu w którym zostały wprowadzone. Zmiana lub udawanie
> zmiany typów wbudowanych bywa bardzo przydatne
Możesz podać jakieś przykłady takiej przydatności?
> Czyli mówisz, że lepszym rozwiązaniem byłoby użycie fun("aaa")
> anieżeli "aaa".fun(), mam rację?
Przypomniala mi sie pewna historia. Pewien poczatkujacy programista C++
przeciazal sobie operator - (minus) tak zeby mu drukowal wynik. Dlaczego -
a nie + lub cokolwiek innego? Podobno tak mu bylo wygodnie.
Chyba kazdy sie domysla jak skomentowano pomysl.
>> Dlatego w Ruby 2.0 pojawić się ma selector namespace, czyli ograniczenie
>> takich zmian do modułu w którym zostały wprowadzone. Zmiana lub udawanie
>> zmiany typów wbudowanych bywa bardzo przydatne
>
> Możesz podać jakieś przykłady takiej przydatności?
>
> GS
Ponieważ wołanie metod łańcuchem jest bardziej przejrzyste od
zagnieżdżania wołań funkcji, jest też bardziej przejrzyste od
zagnieżdżonych comprehensions. W językach które zwie się pure OO jest to
również bardziej naturalne, Python zdecydowanie taki nie jest i tu się
nie czepiam że tych featuresów w nim nie ma.
Np w Scali można zatruć tylko wybrany scope aby to osiągnąć:
object SomeApp extends Application {
implicit def WrapInt(i:int) = new Object {
def next = i + 1
}
val a = 1
val b = 2 + a
Console println a.next + b.next + 3.next
class MyList[T](l:List[T]) {
def myMap(a:T => T):List[T] = l match {
case x::xs => a(x) :: xs.myMap(a)
case _ => Nil
}
def myEach(someCode: T => unit) {
l.foreach(e => someCode(e))
}
}
implicit def WrapList[T](l:List[T]) = new MyList(l)
val list = List(1,2,3,4)
import Console.println
var i = 0
list.myMap(1+).myMap(_ * 2).myMap(a => a * a).myEach { e =>
println(i + ": " + e)
i+=1
}
implicit def SomeOther(i:Any) = new Object {
def hello = Console println "hello from " + i
}
1.hello
"blah".hello
Nil.hello
}
W takich językach zazwyczaj nie ma problemów z tworzeniem własnych
konstrukcji typu pętle i warunki, ale to już inna bajka.
lopex
>>>>>> Aa można bez bla("sss")? Samo "sss".fun()?
>>>>>
>>>>> Pisanie obiektowe nie polega na zmienianiu wszystkiego na klasy i
>>>>> metody.
>>>>> A takie "uzdatnianie" typow wbudowanych to chyba nie jest najlepszy
>>>>> pomysl.
>>>>
>>>> w Ruby jest to mozliwe i sprawdza sie calkiem dobrze
>>>
>>> Zdania na ten temat są podzielone.
>>
>> ...w szczegolnosci na grupie pythonowej :)
>
> Pewnie masz trochę racji, aczkolwiek nie do końca - czytałem też
> programistów
> Javy którzy nie byli zachwyceni pomysłem modyfikowania wbudowanych
> typów. Ze
Wiesz, Java jest dalej od Ruby'ego niz Python, wiec taka opinia wcale mnie
nie dziwi. Programista Javy powie Ci tez, ze jak nie zadeklarujesz typu
zmiennej, to nie wiadomo jaki ona ma typ i w ogole jest tragedia. Albo ze
bez klamerek nie widac, gdzie sie koncza bloki kodu. Ze skladnia, ktora
wymusza stosowanie wciec, gwalci jego poczucie wolnosci. Z tymi opiniami
tez sie zgodzisz? :)
> strony deweloperów Pythona najlepszy komentarz to słowo "monkeypatching"
> używane do opisania tego zjawiska. Osobiście uważam, że zaleta to żadna,
> a upierdliwość dla utrzymujących kod znaczna. A już karalne powinno być
> tego
> typu zachowanie w bibliotekach - włączasz sobie bibliotekę X i nagle typy
> wbudowane zaczynają mieć inną semantykę.
Bez przesady -- biblioteki, ktora powoduje tego typu problemy, nikt by nie
uzywal.
No, chyba ze "inna semantyka" oznacza "wiele nowych, przydatnych metod".
Takie rzeczy zapewnia np. Rails (a dokladnie biblioteka Active Support).
Przeciez autor jezyka, chocby nie wiem jak genialny, wszystkich
przydatnych metod nie wymysli. Nie wszystkie metody sa zreszta przydatne
wszystkim. IMHO to, ze framework webowy jest w stanie dodac do
standardowych typow metody przydatne w kontekscie webowym jest bardzo
fajne.
Jedni boja sie dynamicznego typowania, inni rozszerzania standardowych
typow. A prawda jest taka, ze to tylko narzedzie i jak kazde narzedzie
moze byc uzyte dobrze lub zle. Mozna sobie nim pomoc albo zrobic krzywde.
Sle odpowiedzialnosc jest po stronie programisty, nie narzedzia.
Przyklad zastosowania wziety z mojego doswiadczenia: mialem ci ja model, w
ktorym jedno z pol bylo lista. Zeby zapewnic, ze lista jest niepusta,
uzylem dyrektywy validates_presence_of. Ta dyrektywa wywoluje na
sprawdzanym polu metode blank?. Jednak Array#blank? dziala niezbyt
sensownie (jak na moje potrzeby), bo tylko sprawdza, czy tablica ma jakies
elementy. Wiec np. tablica pustych stringow przechodzila walidacje -- IMO
nieprawidlowo. Najprostsze rozwiaznie: zmienilem definicje Array#blank? na
sensowniejsza: jezeli wszystkie elementy sa blank, to lista tez jest
blank. I zalatwione. Ze moja modyfikacja subtelnie "zmienia semantyke"
klasy Array? I bardzo dobrze -- oryginalna semantyka byla do kitu :)
>>> Dlatego w Ruby 2.0 pojawić się ma selector namespace, czyli ograniczenie
>>> takich zmian do modułu w którym zostały wprowadzone. Zmiana lub udawanie
>>> zmiany typów wbudowanych bywa bardzo przydatne
>>
>> Możesz podać jakieś przykłady takiej przydatności?
>
> Ponieważ wołanie metod łańcuchem jest bardziej przejrzyste od
> zagnieżdżania wołań funkcji, jest też bardziej przejrzyste od
> zagnieżdżonych comprehensions.
OK, ale to (dowolne metody i własności wołane na samym obiekcie) zgodnie
z podanym przykładem możesz mieć niewielkim kosztem bez dotykania typów
wbudowanych. Wystarczy je w razie potrzeby rozszerzyć.
> W językach które zwie się pure OO jest to
> również bardziej naturalne,
Kwestia preferencji.
> Python zdecydowanie taki nie jest
Nie jest 'pure OO'? Dlaczego?
[...]
> lopex
> OK, ale to (dowolne metody i własności wołane na samym obiekcie) zgodnie
> z podanym przykładem możesz mieć niewielkim kosztem bez dotykania typów
> wbudowanych. Wystarczy je w razie potrzeby rozszerzyć.
>
tutaj typy nie były rozszerzone, zadziałał mechanizm wołania
'niejawnego' przy dopasowaniu sygnatury. Scala oferuje duuużo więcej
sztuczek.
>> W językach które zwie się pure OO jest to
>> również bardziej naturalne,
>
> Kwestia preferencji.
>
>> Python zdecydowanie taki nie jest
>
> Nie jest 'pure OO'? Dlaczego?
>
Chociażby dlatego że języki pure OO nie narzucają ograniczeń na
hierarchię class, czy system typów i nie tworzą bytów bez potrzeby (nie
ważne jak mało byłoby to przydatne, i ile innych/nowych wad wprowadzało).
dlaczego np nie można tak:
class a(type(None)):pass
ani tak:
class a(type(lambda x:x)):pass
ani:
class a:
def x():pass
class k(type(a.x)):pass
z tego też nie ?
skoro wszystko jest obiektem i jest jednolity system wołań to dlaczego
działa to:
print None.__str__()
a to już nie:
print None.__class__.__str__()
a w ogóle to dlaczego nie działa:
class A:pass
A.__class__
ah, bo trzeba w innej hierarchii:
class A(object):pass
tamto wyleci z języka, także niech będzie...
print type(None)
<type 'NoneType'>
print NoneType
NameError: name 'NoneType' is not defined
to co to w takim razie jest skoro tego nie ma ?
print type(lambda x:x)
<type 'function'>
print function
NameError: name 'function' is not defined
dalej:
class A(object):
pass
class B(A):
pass
print super(B).__class__
co to ma być ? O chyba jakiś wrapper!
print dir(super(B).__dict__)
jak to ? i po kiego potrzebna mu jest instancja żeby zadziałało?
print dir(super(B,B()).__dict__)
to w takim razie dlaczego to nie działa:
print super(str,"").__dict__
ah, przecież str jest nie z tego świata
dalej:
print str.__new__.__class__
<type 'builtin_function_or_method'>
co to ?
builtin_function_or_method
NameError: name 'builtin_function_or_method' is not defined
print str.__dict__.__class__
<type 'dictproxy'>
dictproxy
NameError: name 'dictproxy' is not defined
ech...
strsuper = "".__class__.__bases__[0]
print strsuper()
class c(strsuper):
pass
print c()
a str może... hmm
print object.__dict__.__str__.__class__
hmm, kolejny wrapper
<type 'method-wrapper'>
print object.__dict__.__str__.__class__.__str__.__class__
<type 'wrapper_descriptor'>
print object.__dict__.__str__.__class__.__str__.__class__.__doc__.__class__
<type 'getset_descriptor'>
dziesiątki klas które są a ich nie ma... po co są one udostępnione
użytkownikowi?, wszędzie jakieś wrappery na siłę z których pożytek
prawie żaden (ah, instancja 'function' przydaje się do introspekcji
funkcji), a dlaczego nie jakiś minimalny system klas (zdecydowanie
standardowych) dzięki którym dało by się to zrobić porządnie i spójnie ?
- to jest właśnie pozostałość z przed wprowadzenia klas. Bałagan aż uszy
więdną.
Wspomniany w wątku ruby też nie jest święty i choć nie ma w nim wyżej
wymienionych 'rodzynków' to wprowadza swoje 'kwiatki'.
skoro można
s = "str"
def s.foo
end
to z kolei nie można
class << 1
end
no virtual class for Fixnum (TypeError)
to samo dla symboli:
class << :a
end
Fixnum.new
undefined method `new' for Fixnum:Class (NoMethodError)
ale:
Numeric.new
#<Numeric:0x2840718>
ciekawe do czego takie "nie wiadomo co" może się przydać...
skoro można
2.instance_eval{@a = :foo}
puts 2.instance_variables
@a
puts 2.instance_variable_get(:@a)
foo
to się okazuje że przy Float'ach dostaniemy nową instancję za drugim razem:
2.1.instance_eval{@a = :foo}
puts 2.1.instance_variable_get(:@a)
nil
to akurat wynika z optymalizacji zużycia pamięci gdzie Fixnumy to jedno
wielkie oszustwo (na którym python by dużo więcej zyskał niż ruby btw).
class A << Class
end
can't make subclass of Class (TypeError)
ale od tej dynamicznej strony już można zepsuć:
A = Class.new(Class)
A.new
`new': wrong instance allocation (TypeError)
ała!
A = Class.allocate
puts A.superclass
`superclass': uninitialized class (TypeError)
ojojoj
dopiero teraz:
A.send(:initialize, String)
puts A.new("blah")
blah
Class.allocate.new
`new': can't instantiate uninitialized class (TypeError)
class B < Class.allocate
end
B.new
to już wygląda na "prawie segfault"
`new': allocator undefined for B (TypeError)
Range.allocate
pięknie!
nil..nil
dobrze że to niesegfaultuje... (ale pewnie parę wersji wcześniej tak):
Range.allocate.to_a
`each': can't iterate from NilClass (TypeError)
te kwiatki wynikają _akurat_ ze spójnej hierarchii i jednolitego
protokołu metod, gdzie np, każdy obiekt (a więc i klasy) inicjalizowany
jest przez wołanie metody initialize przez swoją klasę (nawet dla klas
wbudowanych). Prowadzi to do zbytniej dowolności i mieszania gdzie popadnie.
i wreszcie:
class FalseClass
instance_methods.each{|m|undef_method m}
def method_missing name, *args, &block
true.send(name, *args, &block)
end
end
puts false
> true
puts false.class
> TrueClass
puts true == false
> true
puts true & false
> true
puts false.to_s
> true
Ale inaczej niż np w smalltalku struktury sterujące (if, ?:, unless,
repeat, while, ale nie case) nie są oparte o message passing, co z kolei
prowadzi do niespójności która pozwala wykryć oszustwo:
puts !false ? "false" : "true"
>false
Tak więc, czy pure czy nie pure, i nieważne w jakim wydaniu, język ma
być dla ludzi i ma być pragmatyczny.
lopex
> No, chyba ze "inna semantyka" oznacza "wiele nowych, przydatnych metod".
> Takie rzeczy zapewnia np. Rails (a dokladnie biblioteka Active Support).
> Przeciez autor jezyka, chocby nie wiem jak genialny, wszystkich
> przydatnych metod nie wymysli.
OK, ale przecież nie chodzi o to, żeby nie można było rozszerzyć, ale
o to, żebym siadając do cudzego kodu mógł być pewny, że wywołane w nim
"abcdefgh".index('i') rzuci wyjątek, a "abcdefgh".find('i') zwróci -1,
a nie odwrotnie.
> Nie wszystkie metody sa zreszta przydatne
> wszystkim. IMHO to, ze framework webowy jest w stanie dodac do
> standardowych typow metody przydatne w kontekscie webowym jest bardzo
> fajne.
Dodawanie to jeszcze pół biedy, gorzej ze zmianami.
> Jedni boja sie dynamicznego typowania, inni rozszerzania standardowych
> typow. A prawda jest taka, ze to tylko narzedzie i jak kazde narzedzie
> moze byc uzyte dobrze lub zle. Mozna sobie nim pomoc albo zrobic krzywde.
> Sle odpowiedzialnosc jest po stronie programisty, nie narzedzia.
To w zasadzie tak jak wszystko. Tyle, że rzeczywistą _potrzebę_ redefiniowania
typów wbudowanych ciężko mi sobie wyobrazić, a upierdliwość dla utrzymujących
kod jest dość znaczna.
> Przyklad zastosowania wziety z mojego doswiadczenia: mialem ci ja model, w
> ktorym jedno z pol bylo lista. Zeby zapewnic, ze lista jest niepusta,
> uzylem dyrektywy validates_presence_of. Ta dyrektywa wywoluje na
> sprawdzanym polu metode blank?. Jednak Array#blank? dziala niezbyt
> sensownie (jak na moje potrzeby), bo tylko sprawdza, czy tablica ma jakies
> elementy. Wiec np. tablica pustych stringow przechodzila walidacje -- IMO
> nieprawidlowo. Najprostsze rozwiaznie: zmienilem definicje Array#blank? na
> sensowniejsza: jezeli wszystkie elementy sa blank, to lista tez jest
> blank. I zalatwione. Ze moja modyfikacja subtelnie "zmienia semantyke"
> klasy Array? I bardzo dobrze -- oryginalna semantyka byla do kitu :)
Ale była znana i oczekiwana. Nawet jeśli Twoja ma więcej sensu, dla kogoś
kto siądzie do Twojego kodu będzie niespodzianką.
Pozdrawiam
Beorn
--
Daniel 'Beorn' Mróz <be...@alpha.pl> http://127.0.0.1/beorn
[GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---]
[O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*]
[ r++ y+ ]
Twoje zastrzezenia znow przypominaja mi marudzenie Javowca: siadajac do
cudzego kodu nie moge byc pewny, jakiego typu sa zmienne czy parametry
metody...
jak Ty wogole sobie radzisz z programowaniem w Pythonie, majac tak
bojazliwe podejscie? :-)
> To w zasadzie tak jak wszystko. Tyle, że rzeczywistą _potrzebę_
> redefiniowania
> typów wbudowanych ciężko mi sobie wyobrazić, a upierdliwość dla
> utrzymujących
> kod jest dość znaczna.
smiem twierdzic, ze mowisz czysto teoretycznie. z moich doswiadczen
wynika, ze jest wlasnie odwrotnie: przydatnosc znaczna, upierdliwosc
znikoma. o ile, oczywiscie, zmiany sa przemyslane i sensowne.
>> blank. I zalatwione. Ze moja modyfikacja subtelnie "zmienia semantyke"
>> klasy Array? I bardzo dobrze -- oryginalna semantyka byla do kitu :)
>
> Ale była znana i oczekiwana. Nawet jeśli Twoja ma więcej sensu, dla kogoś
> kto siądzie do Twojego kodu będzie niespodzianką.
nie bedzie, gdyz zmiana zostala:
1. przemyslana i przedyskutowana z zespolem -- wszyscy uznali, ze
przydatnosc znacznie przewyzsza potencjalne problemy
2. okomentowana
3. otestowana
Czy tak trudnym jest zrobienie:
s(u'napis).jakas_metoda ?
Dekoratory, proxy i inne takie sprawdzają się tutaj. Używa się na
szeroką skalę i dopisanie tych kilku znaczków nie jest chyba tak
uciążliwe.
Poza tym, sztuka dla sztuki (używanie metod za miast funkcji) to moim
zdaniem rzecz zarezerwowana dla innych dziedzin, nie informatyki.
Szkoda tracić na to czasu. Funkcje są OK. Nie trzeba z nich na siłę
rezygnować.
To, że Ruby ma coś takiego, nie znaczy, że Python też musi mieć. Niech
to pozostaną 2 różne języki. Każdy ma swoje zalety i wady.
>> OK, ale przecież nie chodzi o to, żeby nie można było rozszerzyć, ale
>> o to, żebym siadając do cudzego kodu mógł być pewny, że wywołane w nim
>> "abcdefgh".index('i') rzuci wyjątek, a "abcdefgh".find('i') zwróci -1,
>> a nie odwrotnie.
>
> Twoje zastrzezenia znow przypominaja mi marudzenie Javowca: siadajac do
> cudzego kodu nie moge byc pewny, jakiego typu sa zmienne czy parametry
> metody...
>
> jak Ty wogole sobie radzisz z programowaniem w Pythonie, majac tak
> bojazliwe podejscie? :-)
Nie jestem programistą, tylko administratorem. W związku z czym znacznie
częściej siadam do cudzego kodu żeby go poprawiać czy debugować niż piszę
coś własnego. Po Perlu Python był dla mnie w tej dziedzinie objawieniem
przez swoją prostotę, jasność i _przewidywalność_. Punkt widzenia po prostu
zmienia się wraz z punktem siedzenia.
>> To w zasadzie tak jak wszystko. Tyle, że rzeczywistą _potrzebę_
>> redefiniowania typów wbudowanych ciężko mi sobie wyobrazić,
>> a upierdliwość dla utrzymujących kod jest dość znaczna.
>
> smiem twierdzic, ze mowisz czysto teoretycznie. z moich doswiadczen
> wynika, ze jest wlasnie odwrotnie: przydatnosc znaczna, upierdliwosc
> znikoma. o ile, oczywiscie, zmiany sa przemyslane i sensowne.
To jest duże "o ile".
>>> blank. I zalatwione. Ze moja modyfikacja subtelnie "zmienia semantyke"
>>> klasy Array? I bardzo dobrze -- oryginalna semantyka byla do kitu :)
>>
>> Ale była znana i oczekiwana. Nawet jeśli Twoja ma więcej sensu, dla kogoś
>> kto siądzie do Twojego kodu będzie niespodzianką.
>
> nie bedzie, gdyz zmiana zostala:
> 1. przemyslana i przedyskutowana z zespolem -- wszyscy uznali, ze
> przydatnosc znacznie przewyzsza potencjalne problemy
> 2. okomentowana
> 3. otestowana
Ponownie, kwestia punktu siedzenia. Ja siedzę po stronie klienta który coś
takiego dostał, a teraz musi przeczytać, zrozumieć, zmodyfikować. Komentarz
fajna rzecz, ale im więcej takich zmian, tym wolniej się jednak pracuje.