🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.python
9 messages
9 total messages Started by tikan Mon, 18 Jan 2010 19:24
class A: print A
#27224
Author: tikan
Date: Mon, 18 Jan 2010 19:24
14 lines
1406 bytes
Witam

class A:
    print A

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in A
NameError: name 'A' is not defined

Jak wyjaśnić takie zachowanie interpretera?

Pozdrawiam
Krzysztof Chmiel
Re: class A: print A
#27223
Author: Łukasz Rekucki
Date: Mon, 18 Jan 2010 21:43
20 lines
1845 bytes
On Jan 18, 8:24 pm, tikan <tik...@gmail.com> wrote:
> Witam
>
> class A:
>     print A
>
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 2, in A
> NameError: name 'A' is not defined
>
> Jak wyjaśnić takie zachowanie interpretera?

Tym, że w trakcie wykonywania ciała klasy A, jeszcze jej nie ma. Więc
skoro w aktualnym bloku nie ma nazwy "A" i w aktualnym module też nie
ma nazwy "A", to znaczy, że jej nie ma. Co się spodziewałeś uzyskać ?

>
> Pozdrawiam
> Krzysztof Chmiel
Re: class A: print A
#27229
Author: William Bonawentura
Date: Tue, 19 Jan 2010 10:16
4 lines
1164 bytes
> Jak wyjaśnić takie zachowanie interpretera?

W C++ czy Javie kompilacja jest dwuprzebiegowa i A byłoby znane. 
Interpretacja jest jednoprzebiegowa i A jeszcze nie zostało przypisane. 
Re: class A: print A
#27225
Author: tikan
Date: Tue, 19 Jan 2010 10:55
41 lines
2368 bytes
On 18 Sty, 22:43, Łukasz Rekucki <lreku...@gmail.com> wrote:
> On Jan 18, 8:24 pm, tikan <tik...@gmail.com> wrote:
>
> > Witam
>
> > class A:
> >     print A
>
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> >   File "<stdin>", line 2, in A
> > NameError: name 'A' is not defined
>
> > Jak wyjaśnić takie zachowanie interpretera?
>
> Tym, że w trakcie wykonywania ciała klasy A, jeszcze jej nie ma. Więc
> skoro w aktualnym bloku nie ma nazwy "A" i w aktualnym module też nie
> ma nazwy "A", to znaczy, że jej nie ma. Co się spodziewałeś uzyskać ?
>
>
>
>
>
> > Pozdrawiam
> > Krzysztof Chmiel

Spodziewałem się, że nazwa klasy jest wpisywana do słownika modułu w
linijce class A:
Problem wziął się stąd, że chciałem utworzyć dekorator do metody klasy
przyjmujący obiekt klasy jako argument
class A:
    @my_decorator(A)
    def f(self):
        pass
Ale jak widać nie działa to tak. Może i słusznie, bo w momencie
wywoływania dekoratora nie byłyby znane wszystkie atrybuty klasy i
działanie kodu
byłoby zależne od kolejności definicji funkcji w klasie.

Pozdrawiam
Krzystof Chmiel
Re: class A: print A
#27230
Author: Rob Wolfe
Date: Tue, 19 Jan 2010 11:34
16 lines
1657 bytes

William Bonawentura napisał(a):
> > Jak wyja�ni� takie zachowanie interpretera?
>
> W C++ czy Javie kompilacja jest dwuprzebiegowa i A byloby znane.
> Interpretacja jest jednoprzebiegowa i A jeszcze nie zostalo przypisane.

Tak z ciekawosci, moglbys pokazac analogiczny kod w C++ lub Javie,
ktory dziala:
class A:
    print A

?

RW
Re: class A: print A
#27226
Author: Rob Wolfe
Date: Tue, 19 Jan 2010 11:44
53 lines
3070 bytes

tikan napisał(a):
> On 18 Sty, 22:43, Łukasz Rekucki <lreku...@gmail.com> wrote:
> > On Jan 18, 8:24 pm, tikan <tik...@gmail.com> wrote:
> >
> > > Witam
> >
> > > class A:
> > >     print A
> >
> > > Traceback (most recent call last):
> > >   File "<stdin>", line 1, in <module>
> > >   File "<stdin>", line 2, in A
> > > NameError: name 'A' is not defined
> >
> > > Jak wyjaśnić takie zachowanie interpretera?
> >
> > Tym, że w trakcie wykonywania ciała klasy A, jeszcze jej nie ma. Więc
> > skoro w aktualnym bloku nie ma nazwy "A" i w aktualnym module też nie
> > ma nazwy "A", to znaczy, że jej nie ma. Co się spodziewałeś uzyskać ?
> >
> >
> >
> >
> >
> > > Pozdrawiam
> > > Krzysztof Chmiel
>
> Spodziewałem się, że nazwa klasy jest wpisywana do słownika modułu w
> linijce class A:
> Problem wziął się stąd, że chciałem utworzyć dekorator do metody klasy
> przyjmujący obiekt klasy jako argument
> class A:
>     @my_decorator(A)
>     def f(self):
>         pass
> Ale jak widać nie działa to tak. Może i słusznie, bo w momencie
> wywoływania dekoratora nie byłyby znane wszystkie atrybuty klasy i
> działanie kodu
> byłoby zależne od kolejności definicji funkcji w klasie.

Musisz jeszcze raz bardzo uwaznie przeczytac ten opis:
http://docs.python.org/reference/executionmodel.html

I zrozumiec, ze "class" (podobnie jak "def") jest wykonywalna
instrukcja,
ktora tworzy dowiazanie do bloku kodu,
ktory z kolei jest wykonywany jako calosc.

http://docs.python.org/reference/compound_stmts.html#class-definitions

RW
Re: class A: print A
#27228
Author: Łukasz Rekucki
Date: Tue, 19 Jan 2010 13:07
94 lines
3743 bytes
On Jan 19, 11:55 am, tikan <tik...@gmail.com> wrote:
> On 18 Sty, 22:43, Łukasz Rekucki <lreku...@gmail.com> wrote:
>
>
>
>
>
> > On Jan 18, 8:24 pm, tikan <tik...@gmail.com> wrote:
>
> > > Witam
>
> > > class A:
> > >     print A
>
> > > Traceback (most recent call last):
> > >   File "<stdin>", line 1, in <module>
> > >   File "<stdin>", line 2, in A
> > > NameError: name 'A' is not defined
>
> > > Jak wyjaśnić takie zachowanie interpretera?
>
> > Tym, że w trakcie wykonywania ciała klasy A, jeszcze jej nie ma. Więc
> > skoro w aktualnym bloku nie ma nazwy "A" i w aktualnym module też nie
> > ma nazwy "A", to znaczy, że jej nie ma. Co się spodziewałeś uzyskać ?
>
> > > Pozdrawiam
> > > Krzysztof Chmiel
>
> Spodziewałem się, że nazwa klasy jest wpisywana do słownika modułu w
> linijce class A:
> Problem wziął się stąd, że chciałem utworzyć dekorator do metody klasy
> przyjmujący obiekt klasy jako argument
> class A:
>     @my_decorator(A)
>     def f(self):
>         pass

> Ale jak widać nie działa to tak. Może i słusznie, bo w momencie
> wywoływania dekoratora nie byłyby znane wszystkie atrybuty klasy i
> działanie kodu
> byłoby zależne od kolejności definicji funkcji w klasie.
Zazwyczaj nie musisz znać klasy podczas dekorowania. Wtedy wystarczy
wyciągnąć we wrapperze type(self). Czasem jednak jest to użyteczne i
da się osiągnąć coś zbliżonego za pomocą metaklasy:

def decor(func):
    func._redecor = True
    return func

def real_decor(klass, func):
    def wrapper(*args, **kwargs):
        print "Calling \"%s\" defined in \"%s\"" % (func.__name__,
klass.__name__)
        return func(*args, **kwargs)
    return wrapper

class Meta(type):

    def __new__(cls, name, bases, class_fields):
        klass = type.__new__(cls, name, bases, class_fields)

        for k in klass.__dict__:
            v = getattr(klass, k)
            if hasattr(v, "_redecor"):
                setattr(klass, k, real_decor(klass, v))

        return klass

class A(object):
    __metaclass__ = Meta
    @decor
    def alpha(self): pass

class B(A):

    @decor
    def alpha(self):
        super(B, self).alpha()

    @decor
    def beta(self): pass

a = A()
a.alpha()
b = B()
b.alpha()
b.beta()

>
> Pozdrawiam
> Krzystof Chmiel

Pozdrawiam,
Łukasz Rekucki
Re: class A: print A
#27231
Author: Łukasz Rekucki
Date: Tue, 19 Jan 2010 13:16
31 lines
2031 bytes
On Jan 19, 12:34 pm, Rob Wolfe <r...@smsnet.pl> wrote:
> William Bonawentura napisał(a):
>
> > > Jak wyja�ni� takie zachowanie interpretera?
>
> > W C++ czy Javie kompilacja jest dwuprzebiegowa i A byloby znane.
> > Interpretacja jest jednoprzebiegowa i A jeszcze nie zostalo przypisane.
>
> Tak z ciekawosci, moglbys pokazac analogiczny kod w C++ lub Javie,
> ktory dziala:
> class A:
>     print A
>
> ?
W Javie to pewnie byłoby coś w stylu:

public class A {
	static {
		System.out.println(A.class);
	}
}

Zachowa się podobnie - print się wykona kiedy klasa zostanie wczytana
i zainicjowana przez ClassLoader. Nie mówię, że to to samo, ale jest
blisko.

>
> RW

Pozdrawiam,
Łukasz Rekucki
Re: class A: print A
#27227
Author: tikan
Date: Tue, 19 Jan 2010 18:32
110 lines
4585 bytes
On 19 Sty, 14:07, Łukasz Rekucki <lreku...@gmail.com> wrote:
> On Jan 19, 11:55 am, tikan <tik...@gmail.com> wrote:
>
>
>
> > On 18 Sty, 22:43, Łukasz Rekucki <lreku...@gmail.com> wrote:
>
> > > On Jan 18, 8:24 pm, tikan <tik...@gmail.com> wrote:
>
> > > > Witam
>
> > > > class A:
> > > >     print A
>
> > > > Traceback (most recent call last):
> > > >   File "<stdin>", line 1, in <module>
> > > >   File "<stdin>", line 2, in A
> > > > NameError: name 'A' is not defined
>
> > > > Jak wyjaśnić takie zachowanie interpretera?
>
> > > Tym, że w trakcie wykonywania ciała klasy A, jeszcze jej nie ma. Więc
> > > skoro w aktualnym bloku nie ma nazwy "A" i w aktualnym module też nie
> > > ma nazwy "A", to znaczy, że jej nie ma. Co się spodziewałeś uzyskać ?
>
> > > > Pozdrawiam
> > > > Krzysztof Chmiel
>
> > Spodziewałem się, że nazwa klasy jest wpisywana do słownika modułu w
> > linijce class A:
> > Problem wziął się stąd, że chciałem utworzyć dekorator do metody klasy
> > przyjmujący obiekt klasy jako argument
> > class A:
> >     @my_decorator(A)
> >     def f(self):
> >         pass
> > Ale jak widać nie działa to tak. Może i słusznie, bo w momencie
> > wywoływania dekoratora nie byłyby znane wszystkie atrybuty klasy i
> > działanie kodu
> > byłoby zależne od kolejności definicji funkcji w klasie.
>
> Zazwyczaj nie musisz znać klasy podczas dekorowania. Wtedy wystarczy
> wyciągnąć we wrapperze type(self). Czasem jednak jest to użyteczne i
> da się osiągnąć coś zbliżonego za pomocą metaklasy:
>
...
>
>
>
> > Pozdrawiam
> > Krzystof Chmiel
>
> Pozdrawiam,
> Łukasz Rekucki

Dziękuję, to rozwiązało mój problem.
Oto kod dekoratora imitującego działanie adnotacji @Override z javy:
def override(func):
    func._redecor = True
    return func

def real_override(cls, func):
    if all(not hasattr(base, func.__name__) for base in
cls.__bases__):
        raise Exception("%s does not overrides base class method" %
func.__name__)

    return func

class Meta(type):
    def __new__(cls, name, bases, class_fields):
        klass = type.__new__(cls, name, bases, class_fields)

        for k in klass.__dict__:
            v = getattr(klass, k)
            if hasattr(v, "_redecor"):
                setattr(klass, k, real_override(klass, v))

        return klass

class A(object):
    __metaclass__ = Meta
    def f(self):
        pass
    def g(self):
        pass

class B(A):
    __metaclass__ = Meta

    @override
    def f(self):
        pass #ok

    @override
    def zsd(self):
        pass #error

Traceback (most recent call last):
  File "override.py", line 29, in <module>
    class B(A):
  File "override.py", line 18, in __new__
    setattr(klass, k, real_override(klass, v))
  File "override.py", line 7, in real_override
    raise Exception("%s does not overrides base class method" %
func.__name__)
Exception: zsd does not overrides base class method

Pozdrawiam
Krzysztof Chmiel
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads