Magisches Verhalten in Perl und Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 10. Februar 2007, 16:41

So z.B.:

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    exec ('__builtins__.foo= [1,2,3]')

try:
    foo
except NameError, error:
    print error

IrgendeinekomischeFunktion()
print foo # -> [1, 2, 3]
Auf einmal gibt es auf "Magischerweise" ``foo``.

EDIT:
Und in Perl wird ja auf "Magischerweise" $`, $', auch erzeugt nach dem Gebrauch von regex.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 10. Februar 2007, 16:46

sape hat geschrieben:

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    exec ('__builtins__.foo= [1,2,3]')
Huch?

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    __builtins__.foo = [1,2,3]
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Samstag 10. Februar 2007, 16:56

sape hat geschrieben:So z.B.:

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    exec ('__builtins__.foo= [1,2,3]')
Also in 2.x ist exec schon noch ein Statement, also keine Klammern.
Und wenn du exec nur einen String ohne globals- oder locals-Argument gibst, kannst du das auch gleich ohne exec schreiben.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 10. Februar 2007, 17:28

Leonidas hat geschrieben:
sape hat geschrieben:

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    exec ('__builtins__.foo= [1,2,3]')
Huch?

Code: Alles auswählen

def IrgendeinekomischeFunktion():
    __builtins__.foo = [1,2,3]
birkenfeld hat geschrieben:[...]
Und wenn du exec nur einen String ohne globals- oder locals-Argument gibst, kannst du das auch gleich ohne exec schreiben.
Ja, hab da auf die schnelle nicht darauf geachtet, weil ich das ursprünglich anders machen wollte...

...
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 10. Februar 2007, 17:45

Code: Alles auswählen

#!/usr/bin/perl -w

sub eine_komisch_funktion {
	my $x = 'aabbaa';
	print "Inhalt von \$1: $1 Inhalt von \$`: $` Inhalt von \$': $'\n" if ($x =~ /(ab)/);
	return 1;
}

eine_komisch_funktion();

print $1;
print $`;
print $';

Code: Alles auswählen

./test.pl
Inhalt von $1: ab Inhalt von $`: a Inhalt von $': baa
Use of uninitialized value in print at test.pl line 11.
Use of uninitialized value in print at test.pl line 12.
Use of uninitialized value in print at test.pl line 13.
***Edit*** Noch klarer!

Code: Alles auswählen

#!/usr/bin/perl -w

{
	my $x = 'aabbaa';
	print "Inhalt von \$1: $1 Inhalt von \$`: $` Inhalt von \$': $'\n" if ($x =~ /(ab)/);
}

print $1;
print $`;
print $';

Code: Alles auswählen

./test.pl
Inhalt von $1: ab Inhalt von $`: a Inhalt von $': baa
Use of uninitialized value in print at test.pl line 8.
Use of uninitialized value in print at test.pl line 9.
Use of uninitialized value in print at test.pl line 10.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 10. Februar 2007, 18:00

Die ganze Sache in Perl ist, dass überhaupt in Perl Variablen ohne explizite Zuweisung durch den Programmierer Werte annehmen - egal in welchem Scope. Sowas will ich wirklich, wirklich nicht in Python sehen. Wenn beim matchen mir irgendwelche Variablen erstellt werden, woher will ich wissen, ob nicht bei anderen Dingen noch mehr Variablen gefüllt werden? Oder gar noch andere Dinge passieren?

Ja, das ist eine Sache der Philosophie. Pythons ist "Explicit ist better than implicit" und so will ich meine Sprache auch haben - optimalerweise ohne Ausnahmen. Das Perl nicht so ist und damit gut fährt mag ja sein, das bezweifle ich gar nicht. Aber ich mag das nicht so haben, nutze also Perl nicht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 10. Februar 2007, 18:19

Wenn ich "$1.." möchte, werden sie belegt. Meine Entscheidung.
Wenn ich den Match in Python möchte, werden ObjektVariablen gesetzt, auch wenn die Namen magischerweise nicht sichtbar werden.
Weniger Magisch?
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Samstag 10. Februar 2007, 18:51

PmanX hat geschrieben:Wenn ich "$1.." möchte, werden sie belegt. Meine Entscheidung.
Wenn ich den Match in Python möchte, werden ObjektVariablen gesetzt, auch wenn die Namen magischerweise nicht sichtbar werden.
Weniger Magisch?
Was für Objektvariablen?

Der Match ist ein Objekt vom Typ MatchObject, der von den re.find/search/etc.-Methoden zurückgegeben wird.

Das Matchobjekt hat Instanzvariablen, und die hat es ab seiner Erzeugung. Also: Selbstverständlich weniger magisch.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
BlackJack

Samstag 10. Februar 2007, 19:16

PmanX hat geschrieben:

Code: Alles auswählen

#!/usr/bin/perl -w

sub eine_komisch_funktion {
	my $x = 'aabbaa';
	print "Inhalt von \$1: $1 Inhalt von \$`: $` Inhalt von \$': $'\n" if ($x =~ /(ab)/);
	return 1;
}

eine_komisch_funktion();

print $1;
print $`;
print $';
`eine_komische_funktion()` in dem Python-Beispiel steht für den Regulären Ausdruck in Perl. Also ist Dein Beispiel hier falsch. Das nach der Ausführung von ``$x =~ /(ab)/`` innerhalb der Funktion plötzlich $1..$n und $` und $' auf magische Weise mit Werten belegt sind, was sie vorher nicht waren, ist die Überraschung die man dem Ausdruck so nicht ansieht.

Und wenn man vorher `$1` mit etwas belegt hat und das hinterher benutzen will, fällt man auf die Nase. Das kann einem bei Python nicht passieren: Egal welche Namen ich vorher an was auch immer gebunden habe, nach `match = re.search(…)` sind die immer noch an die selben Objekte gebunden und es sind auch weder im lokalen, noch im globalen Namensraum irgendwelche neuen Namen aufgetaucht. Die Ergebnisse bleiben schön im Namensraum des `match`-Objektes wo sie niemandem auf die Zehen treten.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 10. Februar 2007, 19:16

PmanX, das schöne an Python ist seine Konsistenz und das es wirklich leicht zu erlernen ist und 99%(?) explizit passiert und daher leicht zu durchschauen ist. Solche Konstrukte die etwas implizit tun gehören nicht zu Pythons Philosophie [1]. Aber vielleicht habe ich ja Python auch nicht verstanden ;)

[1] Auch wenn es durchaus Wege gibt in Python diese Regel zu brechen.
PmanX hat geschrieben:Wenn ich "$1.." möchte, werden sie belegt. Meine Entscheidung.
Wenn ich den Match in Python möchte, werden ObjektVariablen gesetzt, auch wenn die Namen magischerweise nicht sichtbar werden.
Weniger Magisch?
Ja weniger magisch ;) Es werden, keine Variablen auf magischer weise erzeugt wie in Perl.

Code: Alles auswählen

#!/usr/bin/perl
use strict;
use warnings;
 
my $foobar = "<foo>blubb</bar>(foobar)";

print "$foobar\n";

$foobar =~ /<\/bar>/;
# Huch was ist den das? Wo kommt den $', $` und$& her? Nicht magisch?! 
print "post: $'\n";
print "pre: $`\n";
print "this: $&\n";

#<foo>blubb</bar>(foobar)
#post: (foobar)
#pre: <foo>blubb
#this: </bar>
Und jetz mal in Python:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
foobar = "<foo>blubb</bar>(foobar)";
print foobar

m = re.search(r'(<\/bar>)', foobar)
_1, _2 = m.span()
print "post: %s" %foobar[_2:]
print "pre: %s" % foobar[:_1]
print "this: %s" % m.group()

#<foo>blubb</bar>(foobar)
#post: (foobar)
#pre: <foo>blubb
#this: </bar>
Die Ausgabe ist die gleiche. Und hier wir nichts auf Magische weise erzeugt, wie in der Perl Variante, sondern alles explizit.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 10. Februar 2007, 19:21

:!: Objektvariablen != Instanzvariablen :?:

Python ist für Götter :wink:

EDIT:

[friedl]Ein erfolgreiches Matching oder eine Substitution setzt (!= erzeugt) eine Reihe von speziellen Variablen ...
Diese Variablen ändern sich nie bei einem erfolgreichen Matching-Versuch, und sie werden immer gesetzt, wenn ein Treffer gefunden wird[/friedl]
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 10. Februar 2007, 20:04

BlackJack hat geschrieben:
PmanX hat geschrieben:

Code: Alles auswählen

#!/usr/bin/perl -w

sub eine_komisch_funktion {
	my $x = 'aabbaa';
	print "Inhalt von \$1: $1 Inhalt von \$`: $` Inhalt von \$': $'\n" if ($x =~ /(ab)/);
	return 1;
}

eine_komisch_funktion();

print $1;
print $`;
print $';
`eine_komische_funktion()` in dem Python-Beispiel steht für den Regulären Ausdruck in Perl. Also ist Dein Beispiel hier falsch. Das nach der Ausführung von ``$x =~ /(ab)/`` innerhalb der Funktion plötzlich $1..$n und $` und $' auf magische Weise mit Werten belegt sind, was sie vorher nicht waren, ist die Überraschung die man dem Ausdruck so nicht ansieht.

Und wenn man vorher `$1` mit etwas belegt hat und das hinterher benutzen will, fällt man auf die Nase. Das kann einem bei Python nicht passieren: Egal welche Namen ich vorher an was auch immer gebunden habe, nach `match = re.search(…)` sind die immer noch an die selben Objekte gebunden und es sind auch weder im lokalen, noch im globalen Namensraum irgendwelche neuen Namen aufgetaucht. Die Ergebnisse bleiben schön im Namensraum des `match`-Objektes wo sie niemandem auf die Zehen treten.
Ich hatte eine Funktion benutzt.

Code: Alles auswählen

 ... =~ m/../ ist ein Operator
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 10. Februar 2007, 20:05

PmanX hat geschrieben: [friedl]Ein erfolgreiches Matching oder eine Substitution setzt (!= erzeugt) eine Reihe von speziellen Variablen ...
[...]
Ach das ist doch Haarspalterei:

Code: Alles auswählen

#!/usr/bin/perl
use strict;
use warnings;
 
my $foobar = "bin leer";

print "$foobar\n";

$foobar =~ /<\/bar>/;
# Huch was ist den das? Wo kommt den $', $` und$& her? Nicht magisch?!
print "post: $'\n";
print "pre: $`\n";
print "this: $&\n";

Code: Alles auswählen

bin leer
Use of uninitialized value in concatenation (.) or string at foobar.pl line 11.
post:
Use of uninitialized value in concatenation (.) or string at foobar.pl line 12.
pre:
Use of uninitialized value in concatenation (.) or string at foobar.pl line 13.
this:
Wie man sieht ist $', $`, $& garnicht vorhanden bzw. initialisiert bei einem nicht erfolgreichen match. Und ob die nun erzeugt werden oder gesetzt werden ist in dem Fall irrelevant, weil ein unerwartetes Verhalten auftritt. -> Erwarten würde ich in jeden Fall das dann eben stattdessen empty strings ausgegeben werden, weil ich davon ausgehen das in jeden Fall $', $`, $& erzeugt wird oder von mir aus auch gesetzt ;)

Ein anderes Inkonsistentes verhalten ist auch $errno, das je nach Kontext als integer oder string interpretiert werden kann.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Samstag 10. Februar 2007, 20:14

sape hat geschrieben:
PmanX hat geschrieben: [friedl]Ein erfolgreiches Matching oder eine Substitution setzt (!= erzeugt) eine Reihe von speziellen Variablen ...
[...]
Ach das ist doch Haarspalterei:

Code: Alles auswählen

#!/usr/bin/perl
use strict;
use warnings;
 
my $foobar = "bin leer";

print "$foobar\n";

$foobar =~ /<\/bar>/;
# Huch was ist den das? Wo kommt den $', $` und$& her? Nicht magisch?!
print "post: $'\n";
print "pre: $`\n";
print "this: $&\n";

Code: Alles auswählen

bin leer
Use of uninitialized value in concatenation (.) or string at foobar.pl line 11.
post:
Use of uninitialized value in concatenation (.) or string at foobar.pl line 12.
pre:
Use of uninitialized value in concatenation (.) or string at foobar.pl line 13.
this:
Wie man sieht ist $', $`, $& garnicht vorhanden bzw. initialisiert bei einem nicht erfolgreichen match. Und ob die nun erzeugt werden oder gesetzt werden ist in dem Fall irrelevant, weil ein unerwartetes Verhalten auftritt. -> Erwarten würde ich in jeden Fall das dann eben stattdessen empty strings ausgegeben werden, weil ich davon ausgehen das in jeden Fall $', $`, $& erzeugt wird oder von mir aus auch gesetzt ;)

Ein anderes Inkonsistentes verhalten ist auch $errno, das je nach Kontext als integer oder string interpretiert werden kann.
Wo ist hier ein erfolgreiches Matching?
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Samstag 10. Februar 2007, 20:17

PmanX hat geschrieben:[...]
Wo ist hier ein erfolgreiches Matching?
Liest du eigentlich was ich schreibe?
Antworten