Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

x.replace([args]) a nie replace(x, [args])

28 views
Skip to first unread message

jacek....@gmail.com

unread,
Nov 5, 2007, 9:10:22 AM11/5/07
to
Zaletą języka Python jest to, że wszystko w nim jest obiektem. W PHP
np. funkcja str_replace działa tak:
str_replace("abc", "b", "s");
i teraz z ciągu 'abc' 'b' zamieniane jest na 's'
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? 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ć?

mvoicem

unread,
Nov 5, 2007, 9:18:02 AM11/5/07
to
jacek....@gmail.com wrote:

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.

jacek....@gmail.com

unread,
Nov 5, 2007, 9:28:13 AM11/5/07
to
Aa można bez bla("sss")? Samo "sss".fun()?

Piotr Husiatynski

unread,
Nov 5, 2007, 10:29:04 AM11/5/07
to
Dnia Mon, 05 Nov 2007 06:28:13 -0800, jacek.jackweb napisał(a):

> 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.

jacek....@gmail.com

unread,
Nov 5, 2007, 1:23:00 PM11/5/07
to
Czyli mówisz, że lepszym rozwiązaniem byłoby użycie fun("aaa")
anieżeli "aaa".fun(), mam rację?

Przemysław Kowalczyk

unread,
Nov 5, 2007, 1:45:03 PM11/5/07
to
On Mon, 05 Nov 2007 16:29:04 +0100, Piotr Husiatynski
<phusia...@gmail.com> wrote:
>
>> 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/

Grzegorz Staniak

unread,
Nov 5, 2007, 2:27:16 PM11/5/07
to
On 05.11.2007, Przemysław Kowalczyk <som...@microsoft.com> wroted:

>>> 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>

Przemysław Kowalczyk

unread,
Nov 5, 2007, 3:12:47 PM11/5/07
to
On Mon, 05 Nov 2007 20:27:16 +0100, Grzegorz Staniak <gsta...@wp.pl>
wrote:

>
>>>> 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 :)

mvoicem

unread,
Nov 5, 2007, 3:21:32 PM11/5/07
to
jacek....@gmail.com wrote:

> 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.

Rob Wolfe

unread,
Nov 5, 2007, 4:10:05 PM11/5/07
to
jacek....@gmail.com writes:

> 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

Grzegorz Staniak

unread,
Nov 6, 2007, 5:04:35 AM11/6/07
to
On 05.11.2007, Przemysław Kowalczyk <som...@microsoft.com> wroted:

>>>>> 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ę.

Jaroslaw Zabiello

unread,
Nov 6, 2007, 7:02:11 AM11/6/07
to
On Mon, 05 Nov 2007 14:10:22 -0000, <jacek....@gmail.com> wrote:

> 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

Marcin Mielżyński

unread,
Nov 6, 2007, 7:45:11 AM11/6/07
to
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 i jest w językach bardzo
popularne (io, javascript, smalltalk, self, clos, itd). Widać również
tendencje do wprowadzania podobnych możliwości w nowszych językach: C#
(extension methods) czy Scali (views, implicits).

lopex

Grzegorz Staniak

unread,
Nov 6, 2007, 7:58:47 AM11/6/07
to
On 06.11.2007, Marcin Mielżyński <lo...@gazeta.pl> wroted:

>> 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?

Piotr Husiatynski

unread,
Nov 6, 2007, 10:26:54 AM11/6/07
to
Dnia Mon, 05 Nov 2007 10:23:00 -0800, jacek.jackweb napisał(a):

> 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.

Marcin Mielżyński

unread,
Nov 6, 2007, 3:19:10 PM11/6/07
to
Grzegorz Staniak pisze:

> On 06.11.2007, Marcin Mielżyński <lo...@gazeta.pl> wroted:

>> 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

Przemysław Kowalczyk

unread,
Nov 6, 2007, 3:45:35 PM11/6/07
to
On Tue, 06 Nov 2007 11:04:35 +0100, Grzegorz Staniak <gsta...@wp.pl>
wrote:

>>>>>> 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 :)

Grzegorz Staniak

unread,
Nov 6, 2007, 4:17:41 PM11/6/07
to
On 06.11.2007, Marcin Mielżyński <lo...@gazeta.pl> wroted:

>>> 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

Marcin Mielżyński

unread,
Nov 6, 2007, 10:25:24 PM11/6/07
to
Grzegorz Staniak pisze:

> On 06.11.2007, Marcin Mielżyński <lo...@gazeta.pl> wroted:
>

> 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

Grzegorz Staniak

unread,
Nov 7, 2007, 2:30:28 AM11/7/07
to
On 06.11.2007, Przemysław Kowalczyk <som...@microsoft.com> wroted:

> 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ą.

William

unread,
Nov 7, 2007, 3:34:50 AM11/7/07
to
IMHO najlepszym rozwiązaniem byłoby nie rozszerzanie typów wbudowanych tylko wprowadzenie do __globals__ konstruktorów literałów, czyli jeśli w module umieszczę np.

__unicode_constructor__ = MyUnicodeString

to w tym zakresie widoczności wyrażenie:

x = u'napis'

przełoży się na:

x = MyUnicodeString( u'napis' )

Daniel Mroz

unread,
Nov 7, 2007, 3:52:05 AM11/7/07
to
No to już byłby horror przy edycji cudzego kodu.


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+ ]

Przemysław Kowalczyk

unread,
Nov 7, 2007, 2:01:46 PM11/7/07
to
On Wed, 07 Nov 2007 08:30:28 +0100, Grzegorz Staniak <gsta...@wp.pl>
wrote:
>

>> 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.

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

Jakub Stolarski

unread,
Nov 7, 2007, 2:21:26 PM11/7/07
to

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.

Grzegorz Staniak

unread,
Nov 16, 2007, 2:24:18 PM11/16/07
to
On 07.11.2007, Przemysław Kowalczyk <som...@microsoft.com> wroted:

>> 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.

0 new messages