Verfasst: Freitag 1. September 2006, 11:54
Mal eine Frage: An sich wirken ja Ruby und Python sehr ähnlich. Was sind eigentlich die genauen Unterschiede der beiden Sprachen neben Einrückung versus "end".
Seit 2002 Diskussionen rund um die Programmiersprache Python
https://www.python-forum.de/
Vorteile: Performance, eine mir Angenehmere Denkweise (eben der ganze Zen of Python, zum beispiel "Explizit is better than implizit" wie es bei Ruby manchmal der Fall ist), die LCs, Generatoren, Einrücken, Syntax insgesammt, wesentlich bessere Dokumentation, Unterstützung von Unicode. Und auch Pythons Art des Principle of least Surprise ist für mich weniger überraschend als Rubys POLS. Daneben mag ich die Leute in der Community - was aber nicht heißen soll, das Rubys Community schlecht ist, aber ich fühl mich hier einfach mehr "daheim".Danie hat geschrieben:Hmm ich find nicht das, was ich Suche. Ich wüsste eben gerne, was die Vorteile von Python sind gegenüber Ruby.
Es ist teilweise auch das Feeling - ich finde den Weg etwas auf Python zu lösen wesentlich eher zu meiner Denkweise passend als wie das in Ruby gelöst werden würde.Danie hat geschrieben:Oder ist es gar nicht zu beschreiben und es ist einfach nur das Feeling? Was ich kaum glauben kann, denn ohne Grund nehmen große Unternehmen wie Google nicht gerade Python, oder?
Tcl? Blödsinn beiseite, aber Spass macht es sowohl in Ruby als auch in Python zu schreiben, vor allem wenn die Programme dann auch noch funktionieren.Danie hat geschrieben:Anders ausgedrückt: Ich liebe C und Objective-C. Ich liebe die Syntax davon und es gefällt mir, darin Programme zu schreiben, weil es mich glücklich macht. Wo denkt ihr, wäre ich besser aufgehoben?
Vier von den Fünf Punkten des "Spirit of C" aus dem C Standard sind auch auf Python übertragbar. Ich denke Python ist näher an C als Ruby. Das ist vom "Feeling" eher in der Perl Ecke anzusiedeln.Danie hat geschrieben:Anders ausgedrückt: Ich liebe C und Objective-C. Ich liebe die Syntax davon und es gefällt mir, darin Programme zu schreiben, weil es mich glücklich macht. Wo denkt ihr, wäre ich besser aufgehoben?
Na ja, denke das hat eher historische Gründe: Es hat sich halt erst einmal nur Python angeboten.Danie hat geschrieben:Oder ist es gar nicht zu beschreiben und es ist einfach nur das Feeling? Was ich kaum glauben kann, denn ohne Grund nehmen große Unternehmen wie Google nicht gerade Python, oder?
Code: Alles auswählen
class Info
def hallo
print "Hallo"
end
end
x = Info.new
def x.welt
print " Welt"
end
x.hallo
x.welt
Code: Alles auswählen
module Debug
def wer_bin_ich?
"#{self.class.name} ; #{self.to_s}"
end
end
class Phonograph
include Debug #Funktion wird hinzugefügt
...
end
class EightTrack
include Debug
...
end
ph = Phonograph.new("Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.wer_bin_ich? -> "Phonograph : Blues"
et.wer_bin_ich? -> "EightTrack : Surrealistic Pillow"
Code: Alles auswählen
class BlockExample
def m1(&b)
b.call(42) # Block wird mit den Wert 42 gestartet
end
def m2
if block_given? then yield # Block wird ausgeführt
end
end
end
be = BlockExample.new
be.m1 {|arg1|,print arg1} -> 42
be.m2 {print "Hallo"} -> "Hallo"
Code: Alles auswählen
class MyClass
def info
"I am alive"
end
end
c = MyClass.new
print c.send(:info) -> I am alive
Code: Alles auswählen
class Info:
def hallo(self):
print "Hallo"
x = Info()
def welt():
print "Welt"
x.welt = welt
x.hallo()
x.welt()
Du hast hier dem Objekt eine Methode hinzugefügt und nicht der Klasse. Das geht in Python auch:Zambo hat geschrieben:1.) Es ist z.B. ohne Probleme möglich, während der Laufzeit, Methoden zu einer Klasse hinzuzufügen.
z.B.Code: Alles auswählen
class Info def hallo print "Hallo" end end x = Info.new def x.welt print " Welt" end x.hallo x.welt
Code: Alles auswählen
import new
class Info(object):
def hallo(self):
print 'Hallo'
x = Info()
def welt(self):
print 'Welt'
x.welt = new.instancemethod(welt, x, Info)
x.hallo()
x.welt()
Dreh den letzten Satz mal um: Mix-Ins lassen sich durch Mehrfachvererbung realisieren.2.) Es gibt Mix-Ins. Das heißt, man schreibt eine Funktion und kann diese zu einer Klasse hinzumischen.
Besonders Cool ist das, wenn man fertige Funktionalität von Ruby zu einer Klasse hinzufügt.Code: Alles auswählen
module Debug def wer_bin_ich? "#{self.class.name} ; #{self.to_s}" end end class Phonograph include Debug #Funktion wird hinzugefügt ... end class EightTrack include Debug ... end ph = Phonograph.new("Blues") et = EightTrack.new("Surrealistic Pillow") ph.wer_bin_ich? -> "Phonograph : Blues" et.wer_bin_ich? -> "EightTrack : Surrealistic Pillow"
Damit läßt sich natürlich auch Mehrfachvererbung realisieren.
Code: Alles auswählen
class Debug(object):
def wer_bin_ich(self):
return '%s : %s' % (self.__class__.__name__, self)
class Sound(object):
pass
class Phonograph(Sound, Debug):
def __init__(self, data):
self.data = data
def __str__(self):
return self.data
class EightTrack(Sound, Debug):
def __init__(self, data):
self.data = data
def __str__(self):
return self.data
ph = Phonograph('Blues')
et = EightTrack('Surrealistic Pillow')
print ph.wer_bin_ich()
print et.wer_bin_ich()
Im Prinzip handelt es sich einfach um anonyme Funktionen.3.) Es gibt Blöcke.
Diese Möglichkeit kommt aus der funktionalen Programmierung. Im Prinzip handelt es sich dabei um Listen von Anweisungen.
An dieser Stelle hat Python den Nachteil, dass in ``lambda``-Ausdrücken keine Anweisungen möglich sind. Das heisst, ``print`` ist nicht drin und muss durch einen Funktionsaufruf ersetzt werden.Programmierer können Blöcke mit Parametern versehen und als Argumente von Methodenaufrufen verwenden:
Code: Alles auswählen
class BlockExample def m1(&b) b.call(42) # Block wird mit den Wert 42 gestartet end def m2 if block_given? then yield # Block wird ausgeführt end end end be = BlockExample.new be.m1 {|arg1|,print arg1} -> 42 be.m2 {print "Hallo"} -> "Hallo"
Code: Alles auswählen
import sys
def m1(func):
func(42)
def m2(func):
func()
m1(lambda arg1: sys.stdout.write(str(arg1) + '\n'))
m2(lambda: sys.stdout.write('Hallo\n'))
Closures sind in Python auch möglich.Damit sind natürlich auch Closures(Über den Lambda-Befehl ) möglich.
Das geht auch in Python:4.) Ruby kann dynamisch Methoden aufrufen.
Code: Alles auswählen
class MyClass def info "I am alive" end end c = MyClass.new print c.send(:info) -> I am alive
Code: Alles auswählen
class MyClass(object):
def info(self):
return 'I am alive'
c = MyClass()
print getattr(c, 'info')()
Ausser Anweisungen in Blöcken habe ich nichts grosses in Deinen Beispielen entdecken können.Ich könnte natürlich noch ein paar weitere Beispiele zeigen, aber ich denke es ist klar geworden, das Ruby schon ein paar Möglichkeiten hat, die Python nicht bietet.
Das geht durch erben.Zambo hat geschrieben:2.) Es gibt Mix-Ins. Das heißt, man schreibt eine Funktion und kann diese zu einer Klasse hinzumischen.
Mich würde mal interessieren: Wann braucht man das? Hat das schon mal jemand verwendet? IMO wird der Code dadurch unübersichtlich (weil der Code der Klasse verstreut wird), oder übersehe ich einen gravierenden Vorteil?1.) Es ist z.B. ohne Probleme möglich, während der Laufzeit, Methoden zu einer Klasse hinzuzufügen.
Code: Alles auswählen
module Summable
def sum
inject { |v,n| v+n }
end
end
class Array
include Summable
end
class Range
include Summable
end
[1,2,3,4,5].sum -> 15
('a'..'m').sum -> "abcdefghijklm"
Also ich habe das mal benutzt, um eine Webanwendung während sie lief upzudaten.mawe hat geschrieben:Hi!
Mich würde mal interessieren: Wann braucht man das? Hat das schon mal jemand verwendet? IMO wird der Code dadurch unübersichtlich (weil der Code der Klasse verstreut wird), oder übersehe ich einen gravierenden Vorteil?1.) Es ist z.B. ohne Probleme möglich, während der Laufzeit, Methoden zu einer Klasse hinzuzufügen.
Gruß, mawe
Das ist eine nette Lösung wenn man einen Haufen Funktionen/Methoden hat, die man zur Laufzeit auf Grundlage von irgendwelchen externen Daten zu Klassen zusammensetzen möchte. Dann würde das Klassenobjekt selbst aber auch dynamisch erzeugt.mawe hat geschrieben:Mich würde mal interessieren: Wann braucht man das? Hat das schon mal jemand verwendet? IMO wird der Code dadurch unübersichtlich (weil der Code der Klasse verstreut wird), oder übersehe ich einen gravierenden Vorteil?1.) Es ist z.B. ohne Probleme möglich, während der Laufzeit, Methoden zu einer Klasse hinzuzufügen.
Das ist aber nur ein kosmetischer Unterschied. Man kann halt keine anonymen Blöcke definieren, na und, dann gibt man dem Kind halt einen Namen und definiert eine lokale Funktion.Zambo hat geschrieben:Das mit den Blöcken hat BlackJack schon zugegeben, dass das in Python so nicht möglich ist. Was natürlich schon für sich alleine ein Grund seien kann, Ruby vorzuziehen.
Das sieht aus nach "zur Laufzeit Basisklassen hinzufügen". Das geht grundsätzlich schon:Aber bei den Mix-Ins muß ich doch widersprechen. Natürlich kann man Mix-Ins über Mehrfachvererbung realisieren. Aber das Konzept geht bei Ruby doch um einiges weiter, als es bei Python möglich ist. Zum Beispiel möchte ich schon gerne wissen, ob dies in Python auch so möglich wäre?
Code: Alles auswählen
module Summable def sum inject { |v,n| v+n } end end class Array include Summable end class Range include Summable end [1,2,3,4,5].sum -> 15 ('a'..'m').sum -> "abcdefghijklm"
Code: Alles auswählen
In [44]: class A:
....: pass
....:
In [45]: class B:
....: def test(self):
....: print 'b'
....:
In [46]: a = A()
In [47]: a.test()
---------------------------------------------------------------------------
exceptions.AttributeError Traceback (most recent call last)
/home/marc/<ipython console>
AttributeError: A instance has no attribute 'test'
In [48]: A.__bases__ += (B,)
In [49]: a.test()
b
Code: Alles auswählen
import operator
NO_DEFAULT = object()
def my_sum(iterable, default=NO_DEFAULT):
iterator = iter(iterable)
try:
first = iterator.next()
except StopIteration:
if default is NO_DEFAULT:
raise TypeError('empty iterable without default')
else:
return default
return reduce(operator.add, iterator, first)
print my_sum(('H', 'a', 'l', 'l', 'o')) # -> 'Hallo'
print my_sum(xrange(6)) # -> 15
print my_sum([], 0.0) # -> 0.0
print my_sum('') # Raises Exception.
Du hast gesagt Dir fehlen ein paar Dinge in Python, die in Ruby möglich sind und es stellte sich heraus, das vieles davon in Python auch möglich ist.Nebenbei, was großes soll man auch nicht in den Beispielen entdecken. Es soll nur ein paar Konzepte aufzeigen, die ich in Ruby besonders gelungen finde.
Es ist einfach eine Frage des Geschmacks. Durch die Blöcke wird meiner Meinung nach der Code besser lesbar und dadurch natürlich leichter zu warten. Aber man muß es natürlich nicht verwenden. Jeder wie er will. Natürlich kann man kann man alles was man in Ruby programmiert auch in Python machen. Das ist doch klar. Aber um es überspitzt zu sagen; Man kann auch alles in Assembler programmieren. Aber wer will das schon.BlackJack hat geschrieben:Das ist aber nur ein kosmetischer Unterschied. Man kann halt keine anonymen Blöcke definieren, na und, dann gibt man dem Kind halt einen Namen und definiert eine lokale Funktion.Zambo hat geschrieben:Das mit den Blöcken hat BlackJack schon zugegeben, dass das in Python so nicht möglich ist. Was natürlich schon für sich alleine ein Grund seien kann, Ruby vorzuziehen.
Also was du an Code geschrieben hast, ist eher ein Argument für Ruby Nicht böse nehmenDas sieht aus nach "zur Laufzeit Basisklassen hinzufügen". Das geht grundsätzlich schon:Aber bei den Mix-Ins muß ich doch widersprechen. Natürlich kann man Mix-Ins über Mehrfachvererbung realisieren. Aber das Konzept geht bei Ruby doch um einiges weiter, als es bei Python möglich ist. Zum Beispiel möchte ich schon gerne wissen, ob dies in Python auch so möglich wäre?
Code: Alles auswählen
module Summable def sum inject { |v,n| v+n } end end class Array include Summable end class Range include Summable end [1,2,3,4,5].sum -> 15 ('a'..'m').sum -> "abcdefghijklm"
Allerdings kann man bei Typen die in C implementiert sind, entscheiden ob die auf diese Weise verändert werden dürfen und das ist bei den eingebauten Typen ist nicht der Fall.Code: Alles auswählen
In [44]: class A: ....: pass ....: In [45]: class B: ....: def test(self): ....: print 'b' ....: In [46]: a = A() In [47]: a.test() --------------------------------------------------------------------------- exceptions.AttributeError Traceback (most recent call last) /home/marc/<ipython console> AttributeError: A instance has no attribute 'test' In [48]: A.__bases__ += (B,) In [49]: a.test() b
Und das wird in Python auch üblicherweise nicht so gemacht. Wie mawe schon sagte, man zersplittert so die Definition von Klassen.
Wenn man ein generisches Summieren haben möchte, dann definiert man eine entsprechende Funktion.
Code: Alles auswählen
import operator NO_DEFAULT = object() def my_sum(iterable, default=NO_DEFAULT): iterator = iter(iterable) try: first = iterator.next() except StopIteration: if default is NO_DEFAULT: raise TypeError('empty iterable without default') else: return default return reduce(operator.add, iterator, first) print my_sum(('H', 'a', 'l', 'l', 'o')) # -> 'Hallo' print my_sum(xrange(6)) # -> 15 print my_sum([], 0.0) # -> 0.0 print my_sum('') # Raises Exception.
Ja, die Hälfte. Der Rest geht entweder nicht oder nur durch einen so hohen Aufwand, dass die Verwendung von Phython kaum zu rechtfertigen ist.Du hast gesagt Dir fehlen ein paar Dinge in Python, die in Ruby möglich sind und es stellte sich heraus, das vieles davon in Python auch möglich ist.Nebenbei, was großes soll man auch nicht in den Beispielen entdecken. Es soll nur ein paar Konzepte aufzeigen, die ich in Ruby besonders gelungen finde.
Das mach IMHO zum Beispiel dann Sinn, wenn du in deinem Programm ein externes Modul verwendest und dem einfach eine Sinnvolle Methode noch fehlt. Nun kann man es einfach hinzufügen, ohne das Ursprüngliche Modul zu "patchen"...mawe hat geschrieben:Mich würde mal interessieren: Wann braucht man das? Hat das schon mal jemand verwendet? IMO wird der Code dadurch unübersichtlich (weil der Code der Klasse verstreut wird), oder übersehe ich einen gravierenden Vorteil?