🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.python
25 messages
25 total messages Started by Michal M Tue, 15 Dec 2009 21:39
Python i importowanie
#27037
Author: Michal M
Date: Tue, 15 Dec 2009 21:39
42 lines
2481 bytes
Witam

Ostatnio się bardzo zdziwiłem faktem jak działa importowanie w
Pythonie. Taki przykład:

module1.py
------------------------
class Test1(object):
    my_var = 'a'

    @staticmethod
    def change():
        Test1.my_var = 'b'
=============
module2.py
-----------------------
import module1

module1.Test1.change()
print module1.Test1.my_var
============
module3.py
----------------------
from module1 import Test1

print Test1.my_var
===========

Zakładając, że wszystko się wykonuje w jednym programie. Najpierw
module2 ustawia zmienną instancji klasy Test1 na wartość 'b'.
Tak więc w module3 spodziewałem się ujrzeć 'b', a jest 'a'.
Wygląda to tak, że from .... import rzeczywiście importuje do swojej
przestrzeni czyli hmm... tak jakby robił kopię obiektu.
Czytając wszelakie materiały nie widziałem (lub przegapiłem, lub nie
zrozumiałem) wzmiankę o takim zachowaniu.

Teraz pytanie, co zrobić, aby w module3 mieć dostęp do TEGO SAMEGO
obiektu Test1 co w module1 i w module2 ale nie musieć pisać za każdym
razem module1.Test1.my_var.

Pozdrawiam
Michał
Re: Python i importowanie
#27038
Author: Łukasz Rekucki
Date: Tue, 15 Dec 2009 23:15
52 lines
3020 bytes
On Dec 15, 10:39 pm, Michal M <mier...@swietochlowice.org> wrote:
> Witam
>
> Ostatnio się bardzo zdziwiłem faktem jak działa importowanie w
> Pythonie. Taki przykład:
>
> module1.py
> ------------------------
> class Test1(object):
>     my_var = 'a'
>
>     @staticmethod
>     def change():
>         Test1.my_var = 'b'
> =============
> module2.py
> -----------------------
> import module1
>
> module1.Test1.change()
> print module1.Test1.my_var
> ============
> module3.py
> ----------------------
> from module1 import Test1
>
> print Test1.my_var
> ===========
>
> Zakładając, że wszystko się wykonuje w jednym programie.
Ok, ale co jest w tym programie, bo liczy się kolejność importowania
tych modułów.

> Najpierw module2 ustawia zmienną instancji klasy Test1 na wartość 'b'.
> Tak więc w module3 spodziewałem się ujrzeć 'b', a jest 'a'.
> Wygląda to tak, że from .... import rzeczywiście importuje do swojej
> przestrzeni czyli hmm... tak jakby robił kopię obiektu.
Nie. Import .. from .. jedynie dodaje do słownika odpowiednie nazwy,
które prowadzą do tych samych obiektów. Z tego co pamiętam, istnieje
sposób żeby python zaimportował to samo 2 razy, ale nie jest to aż
takie proste. Moduł ten musiałby być dostępny pod dwoma różnymi
nazwami.

> Czytając wszelakie materiały nie widziałem (lub przegapiłem, lub nie
> zrozumiałem) wzmiankę o takim zachowaniu.
>
> Teraz pytanie, co zrobić, aby w module3 mieć dostęp do TEGO SAMEGO
> obiektu Test1 co w module1 i w module2 ale nie musieć pisać za każdym
> razem module1.Test1.my_var.
>
> Pozdrawiam
> Michał
Re: Python i importowanie
#27040
Author: Rob Wolfe
Date: Wed, 16 Dec 2009 09:48
54 lines
2665 bytes

Michal M napisał(a):
> Witam
>
> Ostatnio się bardzo zdziwiłem faktem jak działa importowanie w
> Pythonie. Taki przykład:
>
> module1.py
> ------------------------
> class Test1(object):
>     my_var = 'a'
>
>     @staticmethod
>     def change():
>         Test1.my_var = 'b'
> =============
> module2.py
> -----------------------
> import module1
>
> module1.Test1.change()
> print module1.Test1.my_var
> ============
> module3.py
> ----------------------
> from module1 import Test1
>
> print Test1.my_var
> ===========
>
> Zakładając, że wszystko się wykonuje w jednym programie. Najpierw
> module2 ustawia zmienną instancji klasy Test1 na wartość 'b'.
> Tak więc w module3 spodziewałem się ujrzeć 'b', a jest 'a'.
> Wygląda to tak, że from .... import rzeczywiście importuje do swojej
> przestrzeni czyli hmm... tak jakby robił kopię obiektu.
> Czytając wszelakie materiały nie widziałem (lub przegapiłem, lub nie
> zrozumiałem) wzmiankę o takim zachowaniu.

Twierdzisz, ze masz np. program `main.py` postaci:
import module2
import module3

i raz widzisz 'a' a raz 'b'?

>
> Teraz pytanie, co zrobić, aby w module3 mieć dostęp do TEGO SAMEGO
> obiektu Test1 co w module1 i w module2 ale nie musieć pisać za każdym
> razem module1.Test1.my_var.

To jest i musi byc ten sam obiekt, o czym mozesz sie latwo przekonac
wyswietlajac sobie wszedzie "id(Test1)".

RW
Re: Python i importowanie
#27042
Author: silver
Date: Wed, 16 Dec 2009 10:23
31 lines
2008 bytes
W dniu 16.12.2009 10:48, Rob Wolfe pisze:
>
>

>
> Twierdzisz, ze masz np. program `main.py` postaci:
> import module2
> import module3
>
> i raz widzisz 'a' a raz 'b'?
>
Ja zrozumiałem że robi tak:
1. Pisze program module1.py i tworzy tam jakąś zmienną
2. Tworzy program module2.py w którym importuje module1.py
3. W programie module2.py zmienia zmienną w module1.py
4. W programie module3.py importuje module2.py i próbuje odczytać 
zmienną, którą z modułu module1.py i ma mieć taką wartość na jaką 
zmienił w module.2py

Importy w pythonie działają podobnie do headerów w C++. To nie jest 
rzeczywisty import rezydującego gdzieś w pamięci modułu. To jest de 
facto rozszerzenie przestrzeni nazw do której masz dostęp. Obiekt klasy 
Test1 w module2.py jest zupełnie innym obiektem niż obiekt w module3.py 
Nic dziwnego, że masz inne wartości.

Aby zrobić to co ty chcesz musiałbyś się zaciekawić komunikacją 
międzyprocesową. Zajrzyj do modułu multiprocessing

--
Pozdrawiam,
silver
Re: Python i importowanie
#27036
Author: silver
Date: Wed, 16 Dec 2009 10:25
31 lines
2026 bytes
W dniu 16.12.2009 10:48, Rob Wolfe pisze:
 >
 >

 >
 > Twierdzisz, ze masz np. program `main.py` postaci:
 > import module2
 > import module3
 >
 > i raz widzisz 'a' a raz 'b'?
 >
Ja zrozumiałem że robi tak:
1. Pisze program module1.py i tworzy tam jakąś zmienną
2. Tworzy program module2.py w którym importuje module1.py
3. W programie module2.py zmienia zmienną w module1.py
4. W programie module3.py importuje module2.py i próbuje odczytać 
zmienną, którą zmienił w module module1.py i ma mieć taką wartość na 
jaką zmienił w module.2py

Importy w pythonie działają podobnie do headerów w C++. To nie jest 
rzeczywisty import rezydującego gdzieś w pamięci modułu. To jest de 
facto rozszerzenie przestrzeni nazw do której masz dostęp. Obiekt klasy 
Test1 w module2.py jest zupełnie innym obiektem niż obiekt w module3.py 
Nic dziwnego, że masz inne wartości.

Aby zrobić to co ty chcesz musiałbyś się zaciekawić komunikacją 
międzyprocesową. Zajrzyj do modułu multiprocessing

-- 
Pozdrawiam,
silver
Re: Python i importowanie
#27063
Author: Michal M
Date: Wed, 16 Dec 2009 10:54
47 lines
2830 bytes
Dziękuję za odpowiedzi.

Mam wrażenie, że już sam nie wiem co robię.

Robię to tak, jakbym pisał program w javie. Po prostu składa się z
wielu plików ale nie uruchamiam ich oddzielnie tylko z jednego.

Dodam, że gdybym zapisał module3 tak:

module3.py
----------------------
import module1

print module1.Test1.my_var
===========

To widzę to czego oczekiwałem, czyli 'b'

Ale w takiej formie:

module3.py
----------------------
from module1 import Test1

print Test1.my_var
===========

Widzę 'a'

Dlatego napisałem, że wygląda to tak, jakby obiekt on zaimportował do
swojej przestrzeni nazw tak jakby kopiował (hmm.. że użyję terminologi
z javy) klasę i tworzył jej instancję w przestrzeni nazw module3 który
to zaimportował. Ale gdy importujemy cały moduł (import module1),
wtedy klasa Test1 jest nadal w swojej przestrzeni gdzie ma atrybut
my_var == 'b'.

To jest oczywiście przykład obrazujący mój problem. Cały program jest
trochę bardziej rozbudowany ale jeśli komuś to pomoże w odpowiedzi to
mogę go gdzieś wystawić (jest dość krótki).

Jeszcze tak przyszło mi na myśl.
Mógłbym zaimportować cały moduł: import module1
i stworzyć zmienną: my_local = module1.Test1.my_var
ale o ile w innych językach byłoby to jakieś ułatwinie to tutaj,
ponieważ w każdej funkcji musiałbym dopisywać global my_local (ale mi
wyszło.. ;) )
to nie wiele mi to da.
Re: Python i importowanie
#27061
Author: Michal M
Date: Wed, 16 Dec 2009 11:29
21 lines
2053 bytes
Dokładnie tak. Te trzy pliki działały jako jeden program (tak jak w
javie) i jak wstawiałem do module3

from module1 import Lang

to widziałem 'a', a jak wstawiałem

import module1

to widziałem 'b'.

Dlatego moje zdziwienie, bo wyglądało jakby te dwa nie powodowały
tylko udostępnienia obiektu w przestrzeni nazw lokalnego modułu ale
importowały (kopiowały) cały obiekt do tego modułu i tworzyły
instancję. Wtedy obiekt Lang z module1 nie byłby tym samym co ten
zaimportowany w module3.

ALE... dzisiaj dziwnym trafem nie mogę odtworzyć tej sytuacji (ten sam
kod, nie zmieniany) i wszystko działa jak Wy i Ja przewidujecie. Wobec
tego wypada mi tylko przeprosić za zamieszanie i podziękować za
odpowiedzi.
Re: Python i importowanie
#27044
Author: i0cus
Date: Wed, 16 Dec 2009 11:33
38 lines
2821 bytes
On 16 Gru, 11:23, silver <sil...@niematakiegoemaila.pl> wrote:
> W dniu 16.12.2009 10:48, Rob Wolfe pisze:
>
>
>
> > Twierdzisz, ze masz np. program `main.py` postaci:
> > import module2
> > import module3
>
> > i raz widzisz 'a' a raz 'b'?
>
> Ja zrozumiałem że robi tak:
> 1. Pisze program module1.py i tworzy tam jakąś zmienną
> 2. Tworzy program module2.py w którym importuje module1.py
> 3. W programie module2.py zmienia zmienną w module1.py
> 4. W programie module3.py importuje module2.py i próbuje odczytać
> zmienną, którą z modułu module1.py i ma mieć taką wartość na jaką
> zmienił w module.2py

I fajnie by było, ale OP napisał też:

> Zakładając, że wszystko się wykonuje w jednym programie.

No więc na moje oko dopasowałeś swoją wersję wyjaśnienia do błędu
opisanego przez użytkownika. ;-)

A mnie błąd użytkownika wygląda na (1) brak importu modułu 2, ew. (2)
za kulisami dzieje się coś, co sprawia, że jednak dostaje świeże
instancje Test1(). Python dość uparcie traktuje moduły jako singletony
i wydaje mi się, że przedstawiony przykład zbytnio spłyca obraz
sytuacji (a przede wszystkim nie oddaje opisanego zachowania -- jeśli
zaimportowany zostanie moduł 2 i moduł 3, to wartości są 'b', gdyż
moduł 1 jest ładowany jednokrotnie).


> --
> Pozdrawiam,
> silver
Re: Python i importowanie
#27064
Author: William Bonawentura
Date: Thu, 17 Dec 2009 07:41
11 lines
1640 bytes
Użytkownik "Michal M" <mmierzwa@tycowaterworks.pl> napisał w wiadomości 
news:52950de7-b700-40e0-964d-0bb7ab394964@x15g2000vbr.googlegroups.com...
> ALE... dzisiaj dziwnym trafem nie mogę odtworzyć tej sytuacji (ten sam
> kod, nie zmieniany) i wszystko działa jak Wy i Ja przewidujecie. Wobec
> tego wypada mi tylko przeprosić za zamieszanie i podziękować za
> odpowiedzi.

Nie piszesz przypadkiem pod Unixem ? Efekt jaki opisujesz może być 
spowodowany sytuacją, gdy interpreter nie potrafi nadpisać lub utworzyć .pyc 
i każdy import powoduje parsowanie .py.
Re: Python i importowanie
#27048
Author: Rob Wolfe
Date: Thu, 17 Dec 2009 11:29
17 lines
1634 bytes
"William Bonawentura" <news@ipartners.pl> writes:

> Użytkownik "Michal M" <mmierzwa@tycowaterworks.pl> napisał w
> wiadomości
> news:52950de7-b700-40e0-964d-0bb7ab394964@x15g2000vbr.googlegroups.com...
>> ALE... dzisiaj dziwnym trafem nie mogę odtworzyć tej sytuacji (ten sam
>> kod, nie zmieniany) i wszystko działa jak Wy i Ja przewidujecie. Wobec
>> tego wypada mi tylko przeprosić za zamieszanie i podziękować za
>> odpowiedzi.
>
> Nie piszesz przypadkiem pod Unixem ? Efekt jaki opisujesz może być
> spowodowany sytuacją, gdy interpreter nie potrafi nadpisać lub
> utworzyć .pyc i każdy import powoduje parsowanie .py.

Nic podobnego. Kod i tak jest ładowany tylko raz.

RW
Re: Python i importowanie
#27046
Author: Radomir Dopieralski
Date: Thu, 17 Dec 2009 17:52
14 lines
1982 bytes
At Wed, 16 Dec 2009 11:23:47 +0100, silver wrote:

> Importy w pythonie działają podobnie do headerów w C++. To nie jest 
> rzeczywisty import rezydującego gdzieś w pamięci modułu. To jest de 
> facto rozszerzenie przestrzeni nazw do której masz dostęp. Obiekt klasy 
> Test1 w module2.py jest zupełnie innym obiektem niż obiekt w module3.py 
> Nic dziwnego, że masz inne wartości.

To nie tak. Modul jest jeden - w obrebie jednego programu - zaimportowanie
go wiele razy i tak zawsze zwroci ten sam obiekt, chyba ze sie zrobi
jakies sztuczki z __import__. Include w C i pochodnych dziala kompletnie
inaczej.
 
Radomir Dopieralski, http://sheep.art.pl
Re: Python i importowanie
#27050
Author: Sebastian Kaliszewski
Date: Fri, 18 Dec 2009 10:11
47 lines
2500 bytes
silver wrote:
> W dniu 16.12.2009 10:48, Rob Wolfe pisze:
>  >
>  >
> 
>  >
>  > Twierdzisz, ze masz np. program `main.py` postaci:
>  > import module2
>  > import module3
>  >
>  > i raz widzisz 'a' a raz 'b'?
>  >
> Ja zrozumiałem że robi tak:
> 1. Pisze program module1.py i tworzy tam jakąś zmienną
> 2. Tworzy program module2.py w którym importuje module1.py
> 3. W programie module2.py zmienia zmienną w module1.py
> 4. W programie module3.py importuje module2.py i próbuje odczytać 
> zmienną, którą zmienił w module module1.py i ma mieć taką wartość na 
> jaką zmienił w module.2py
> 
> Importy w pythonie działają podobnie do headerów w C++. 

Bzdura.

> To nie jest 
> rzeczywisty import rezydującego gdzieś w pamięci modułu. To jest de 
> facto rozszerzenie przestrzeni nazw do której masz dostęp. Obiekt klasy 
> Test1 w module2.py jest zupełnie innym obiektem niż obiekt w module3.py 
> Nic dziwnego, że masz inne wartości.
> 
> Aby zrobić to co ty chcesz musiałbyś się zaciekawić komunikacją 
> międzyprocesową. 

Co???

> Zajrzyj do modułu multiprocessing
> 

Co ma piernik do wiatraka?


pzdr
\SK
-- 
"Never underestimate the power of human stupidity" -- L. Lang
-- 
http://www.tajga.org -- (some photos from my travels)
Re: Python i importowanie
#27051
Author: Sebastian Kaliszewski
Date: Fri, 18 Dec 2009 10:13
27 lines
1893 bytes
Michal M wrote:
> Dokładnie tak. Te trzy pliki działały jako jeden program (tak jak w
> javie) 

Co to znaczy tak jak w Javie?


Pokaż całość -- co importuje co.

Czyli co i gdzie importuje module2 oraz module3.

[...]
> ALE... dzisiaj dziwnym trafem nie mogę odtworzyć tej sytuacji (ten sam
> kod, nie zmieniany) i wszystko działa jak Wy i Ja przewidujecie. Wobec
> tego wypada mi tylko przeprosić za zamieszanie i podziękować za
> odpowiedzi.

Może jednak coś nie było tak samo. Np zapomniałeś zrobić "save" w 
edytorze (to się często zdarza)

pzdr

\SK
-- 
"Never underestimate the power of human stupidity" -- L. Lang
-- 
http://www.tajga.org -- (some photos from my travels)
Re: Python i importowanie
#27052
Author: Michal M
Date: Sun, 20 Dec 2009 21:10
59 lines
2747 bytes
Ok, ten sam problem się powtórzył. Tym razem podam dokładnie przykład.

module1.py
log = None

module2.py
class Log(object):
    def __init__(self):
        pass
    def m(self):
        print "ok"

module3.py
import module1
import module2
import module4

module1.log = module2.Log()
t = module4.Test()
t.use_m()

module4.py
from module1 import log

class Test(object):
    def __init__(self):
        pass
    def use_m(self):
        log.m()


Uruchamiam moduł 3. Ja to widzę tak:
1. importuje moduły 1, 2 i 3 (czyli udostępnia ich przestrzeń poprzez
nazwę modułu w module 3)
2. pod zmienną log w module 1 podstawia instancję klasy Log z modułu 2
3. Pod zmienną t podstawia instancję klasy Test z modułu 4 i próbuje
wykonać jej metodę use_m()
W tym miejscu otrzymuję błąd: AttributeError: 'NoneType' object has no
attribute 'm'

Teraz powiedzmy, że moduł 4 zmienię tak:

module4.py
import module1

class Test(object):
    def __init__(self):
        pass
    def use_m(self):
        module1.log.m()

Czyli wg mnie powinno być to samo, tyle że zamiast bezpośrednio do log
mam dostęp poprzez module1.log.
Zastanawiałem się, czy może samo log.m() nie widzi jako zmiennej
lokalnej i nie potrzeba dodać global log ale też nie pomaga.
Proszę o wyjaśnienie.

Pozdrawiam
Michał
Re: Python i importowanie
#27066
Author: marmarprog
Date: Sun, 20 Dec 2009 21:16
47 lines
2810 bytes
On 16 Gru, 11:25, silver <sil...@niematakiegoemaila.pl> wrote:
> W dniu 16.12.2009 10:48, Rob Wolfe pisze:
>  >
>  >
>
>  >
>  > Twierdzisz, ze masz np. program `main.py` postaci:
>  > import module2
>  > import module3
>  >
>  > i raz widzisz 'a' a raz 'b'?
>  >
> Ja zrozumiałem że robi tak:
> 1. Pisze program module1.py i tworzy tam jakąś zmienną
> 2. Tworzy program module2.py w którym importuje module1.py
> 3. W programie module2.py zmienia zmienną w module1.py
> 4. W programie module3.py importuje module2.py i próbuje odczytać
> zmienną, którą zmienił w module module1.py i ma mieć taką wartość na
> jaką zmienił w module.2py
>
> Importy w pythonie działają podobnie do headerów w C++. To nie jest
> rzeczywisty import rezydującego gdzieś w pamięci modułu. To jest de
> facto rozszerzenie przestrzeni nazw do której masz dostęp. Obiekt klasy
> Test1 w module2.py jest zupełnie innym obiektem niż obiekt w module3.py
> Nic dziwnego, że masz inne wartości.
>
> Aby zrobić to co ty chcesz musiałbyś się zaciekawić komunikacją
> międzyprocesową. Zajrzyj do modułu multiprocessing
>
> --
> Pozdrawiam,
> silver

Po wpisaniu takiego kodu

import module2
import module3
from module1 import Test1
print Test1.my_var

otrzymuje:
b
b
b

Wiec nie wiem w czym jest problem zwłaszcza tych bredni o nie
rzeczywistym importowaniu.
Re: Python i importowanie
#27049
Author: marmarprog
Date: Sun, 20 Dec 2009 22:02
97 lines
4139 bytes
On 20 Gru, 22:10, Michal M <mmier...@tycowaterworks.pl> wrote:
> Ok, ten sam problem się powtórzył. Tym razem podam dokładnie przykład.
>
> module1.py
> log = None
>
> module2.py
> class Log(object):
>     def __init__(self):
>         pass
>     def m(self):
>         print "ok"
>
> module3.py
> import module1
> import module2
> import module4
>
> module1.log = module2.Log()
> t = module4.Test()
> t.use_m()
>
> module4.py
> from module1 import log
>
> class Test(object):
>     def __init__(self):
>         pass
>     def use_m(self):
>         log.m()
>
> Uruchamiam moduł 3. Ja to widzę tak:
> 1. importuje moduły 1, 2 i 3 (czyli udostępnia ich przestrzeń poprzez
> nazwę modułu w module 3)
> 2. pod zmienną log w module 1 podstawia instancję klasy Log z modułu 2
> 3. Pod zmienną t podstawia instancję klasy Test z modułu 4 i próbuje
> wykonać jej metodę use_m()
> W tym miejscu otrzymuję błąd: AttributeError: 'NoneType' object has no
> attribute 'm'
>
> Teraz powiedzmy, że moduł 4 zmienię tak:
>
> module4.py
> import module1
>
> class Test(object):
>     def __init__(self):
>         pass
>     def use_m(self):
>         module1.log.m()
>
> Czyli wg mnie powinno być to samo, tyle że zamiast bezpośrednio do log
> mam dostęp poprzez module1.log.
> Zastanawiałem się, czy może samo log.m() nie widzi jako zmiennej
> lokalnej i nie potrzeba dodać global log ale też nie pomaga.
> Proszę o wyjaśnienie.
>
> Pozdrawiam
> Michał

Python tak działa.
Zmienne można powiedzieć są etykietowane przez nazwę. Oznacza to że
jeżeli użyjemy instrukcji przypisania  to przypiszemy danej etykiecie
nowy obiekt np.
log=None # obiekt None otrzymuje etykietę log
b=log # obiekt None otrzymuje nowa etykietę b
# teraz jeśli napiszę
log=3 # obiekt 3 otrzymuje etykietę log ale etykieta b nadal odnosi
sie do obiektu None (tak samo )

Pisząc
module1.log= ...
modyfikujesz tylko etykiete w przestrzeni nazw modułu modul1. tylko
importy wykonane po tej instrukcji będą widzieć ta zmianę.
Ale dosyć tych bredni.
Jeżeli chcesz zamiast module1.log.m()  pisać log.m() zrezygnuj z
module2 i napisz w module1

class Log(object):
    def __init__(self):
        pass
    def m(self):
        print "ok"
log = None

potem piszesz w dowolmym module
from module1 import log

oczywiście jeśli napiszesz potem "gdzieś" module1.log=... to znów
"gdzieś" odnosić się bedziesz  do innego obiektu.
i możesz z obiektu log pakować  i doczytywać cokolwiek:

log.xxx=3

a winnym module

print log.xxx
Re: Python i importowanie
#27070
Author: Michal M
Date: Sun, 20 Dec 2009 22:40
120 lines
5304 bytes
On 20 Gru, 23:02, marmarprog <marmarp...@gmail.com> wrote:
> On 20 Gru, 22:10, Michal M <mmier...@tycowaterworks.pl> wrote:
>
>
>
>
>
> > Ok, ten sam problem się powtórzył. Tym razem podam dokładnie przykład.
>
> > module1.py
> > log = None
>
> > module2.py
> > class Log(object):
> >     def __init__(self):
> >         pass
> >     def m(self):
> >         print "ok"
>
> > module3.py
> > import module1
> > import module2
> > import module4
>
> > module1.log = module2.Log()
> > t = module4.Test()
> > t.use_m()
>
> > module4.py
> > from module1 import log
>
> > class Test(object):
> >     def __init__(self):
> >         pass
> >     def use_m(self):
> >         log.m()
>
> > Uruchamiam moduł 3. Ja to widzę tak:
> > 1. importuje moduły 1, 2 i 3 (czyli udostępnia ich przestrzeń poprzez
> > nazwę modułu w module 3)
> > 2. pod zmienną log w module 1 podstawia instancję klasy Log z modułu 2
> > 3. Pod zmienną t podstawia instancję klasy Test z modułu 4 i próbuje
> > wykonać jej metodę use_m()
> > W tym miejscu otrzymuję błąd: AttributeError: 'NoneType' object has no
> > attribute 'm'
>
> > Teraz powiedzmy, że moduł 4 zmienię tak:
>
> > module4.py
> > import module1
>
> > class Test(object):
> >     def __init__(self):
> >         pass
> >     def use_m(self):
> >         module1.log.m()
>
> > Czyli wg mnie powinno być to samo, tyle że zamiast bezpośrednio do log
> > mam dostęp poprzez module1.log.
> > Zastanawiałem się, czy może samo log.m() nie widzi jako zmiennej
> > lokalnej i nie potrzeba dodać global log ale też nie pomaga.
> > Proszę o wyjaśnienie.
>
> > Pozdrawiam
> > Michał
>
> Python tak działa.
> Zmienne można powiedzieć są etykietowane przez nazwę. Oznacza to że
> jeżeli użyjemy instrukcji przypisania  to przypiszemy danej etykiecie
> nowy obiekt np.
> log=None # obiekt None otrzymuje etykietę log
> b=log # obiekt None otrzymuje nowa etykietę b
> # teraz jeśli napiszę
> log=3 # obiekt 3 otrzymuje etykietę log ale etykieta b nadal odnosi
> sie do obiektu None (tak samo )
>
> Pisząc
> module1.log= ...
> modyfikujesz tylko etykiete w przestrzeni nazw modułu modul1. tylko
> importy wykonane po tej instrukcji będą widzieć ta zmianę.
> Ale dosyć tych bredni.
> Jeżeli chcesz zamiast module1.log.m()  pisać log.m() zrezygnuj z
> module2 i napisz w module1
>
> class Log(object):
>     def __init__(self):
>         pass
>     def m(self):
>         print "ok"
> log = None
>
> potem piszesz w dowolmym module
> from module1 import log
>
> oczywiście jeśli napiszesz potem "gdzieś" module1.log=... to znów
> "gdzieś" odnosić się bedziesz  do innego obiektu.
> i możesz z obiektu log pakować  i doczytywać cokolwiek:
>
> log.xxx=3
>
> a winnym module
>
> print log.xxx

Dzięki za odpowiedź. To nie brednie to pomaga mi zrozumieć to
zachowanie (choć jeszcze tego nie ogarniam). Mnie to po prostu
wyglądało, że log jest importowane do przestrzeni module4 i zmiana
przypisania do tej zmiennej w module 1 nie jest odzwierciedlana w
module4. Inaczej jest jeśli odwołuję się przez module1.log. Wtedy
odwołuję się do zmiennej właśnie w tamtej przestrzeni nazw (module1).
Nie wiem czy to wyjaśnienie jest zbieżne z tym co ty napisałeś (i
prawidłowe) ale tłumaczy to zachowanie i jest tym co chciałem na
początku przekazać w pierwszym poście.
Ze względu na to, że projekt będzie pewnie trochę większy, zrozumienie
tego ma dla mnie duże znaczenie. Dlatego też, nie chciałbym przenosić
log do modułu w którym jest Log bo chciałbym takie rzeczy trzymać
razem w jednym module aby się później nie pogubić (gdzie ja to
umieściłem.)

Jeszcze raz dziękuję za wyjaśnienie i pozdrawiam.
Re: Python i importowanie
#27069
Author: Łukasz Rekucki
Date: Mon, 21 Dec 2009 01:26
27 lines
2709 bytes
Używanie terminów zmienna i przestrzeń nazw wydaje mi się myląca.
Podstawą jest zrozumienie, że "log" w Pythonie nie jest zmienną, a
jedynie nazwą wskazującą na jakiś obiekt. Tak więc sytuacja wygląda
tak:

0) zaczynasz wykonywanie module3
1) import module1
1.1) do słownika modułu module1 dodawana jest nazwa "log" wskazująca
na obiekt None
2) import module2
2.1) wykonywane jest ciało klasy Log
2.2) do nazwy Log w module2 przypisywana jest nowo utworzona klasa Log
3) import module4
3.1) from module1 import log
3.1.1) moduł "module1" jest już zaimportowany, więc odczytywane jest
na  jaki obiekt wskazuję nazwa "log" w jego słowniku (jest to None)
3.1.2) w słowniku module4 tworzona jest nowa nazwa i wskazuje ona na
None
3.2) Tworzona jest klasa Test (analogicznie do klasy Log)
4) module1.log = module2.Log()  # nazwa log w słowniku module1
wskazuję teraz na nowy obiekt klasy Log. Słownik module4 jest
niezmieniony.
5) t = module4.Test()
6) t.use_m()
6.1) log nie jest lokalne dla use_m, więc jest globalne. Globalnym
kontekstem dla use_m() jest module4. module4.log wskazuję na None ->
błąd.
Re: Python i importowanie
#27065
Author: Michal M
Date: Mon, 21 Dec 2009 08:39
53 lines
3723 bytes
On 21 Gru, 02:26, Łukasz Rekucki <lreku...@gmail.com> wrote:
> Używanie terminów zmienna i przestrzeń nazw wydaje mi się myląca.
> Podstawą jest zrozumienie, że "log" w Pythonie nie jest zmienną, a
> jedynie nazwą wskazującą na jakiś obiekt. Tak więc sytuacja wygląda
> tak:
>
> 0) zaczynasz wykonywanie module3
> 1) import module1
> 1.1) do słownika modułu module1 dodawana jest nazwa "log" wskazująca
> na obiekt None
> 2) import module2
> 2.1) wykonywane jest ciało klasy Log
> 2.2) do nazwy Log w module2 przypisywana jest nowo utworzona klasa Log
> 3) import module4
> 3.1) from module1 import log
> 3.1.1) moduł "module1" jest już zaimportowany, więc odczytywane jest
> na  jaki obiekt wskazuję nazwa "log" w jego słowniku (jest to None)
> 3.1.2) w słowniku module4 tworzona jest nowa nazwa i wskazuje ona na
> None
> 3.2) Tworzona jest klasa Test (analogicznie do klasy Log)
> 4) module1.log = module2.Log()  # nazwa log w słowniku module1
> wskazuję teraz na nowy obiekt klasy Log. Słownik module4 jest
> niezmieniony.
> 5) t = module4.Test()
> 6) t.use_m()
> 6.1) log nie jest lokalne dla use_m, więc jest globalne. Globalnym
> kontekstem dla use_m() jest module4. module4.log wskazuję na None ->
> błąd.

Czyli
from module1 import log
Tworzy nową zmienną (etykietkę jak wy to nazywacie) w przestrzeni
(słowniku) module4 i podstawia pod nią referencję (akurat None, bo się
jeszcze nie wykonało podstawienie instancji Log).
Natomiast
import module1
module1.log
Wskazuje na tą samą zmienną którą zmieniam w module1.
Innymi słowy, po
from module1 import log
mam dwie etykietki log i są one niezależne od siebie.
Muszę z tym uważać
Rozwiązaniem wygodnym byłoby zapisanie w module 4
import module1
log = module1.log
... gdyby nie to, że w każdej funkcji musiałbym dodać
global log
tak?
Wtedy gra nie warta świeczki.

No cóż... każdy język ma swoje udziwnienia. :)

Dziękuję wszystkim za wyjaśnienia.
Re: Python i importowanie
#27067
Author: Michal M
Date: Mon, 21 Dec 2009 08:44
20 lines
2330 bytes
Przepraszam, że odpowiadam sobie ale nie mogłem wyedytować
poprzedniego postu.

Jeszcze takie pytanie. Gdybym zrobił tak:

module4.py

class Test(object):
    def __init__(self):
        from module1 import log
        pass
    def use_m(self):
        log.m()


Czyli zaimportował de facto log po podstawieniu pod niego instancji
Log, to powinno działać? Jeśli umieszczę import w funkcji to
zaimportuje do słownika głównego modułu czy do lokalnego funkcji? Da
się tak w ogóle?
(nie jestem tutaj w stanie sprawdzić)
Re: Python i importowanie
#27071
Author: Bart Ogryczak
Date: Mon, 21 Dec 2009 11:05
12 lines
1681 bytes
On Dec 20, 10:10 pm, Michal M <mmier...@tycowaterworks.pl> wrote:
>  Tym razem podam dokładnie przykład.


Ok, to co tak naprawdę robisz:

>>> m1 = {'log': None}
>>> m2 = {'Log': 'klasa Log'}
>>> m4 = {'log': m1['log']}
>>> m1['log'] = m2['Log']
>>> m1, m2, m4
({'log': 'klasa Log'}, {'Log': 'klasa Log'}, {'log': None})
Re: Python i importowanie
#27072
Author: Michal M
Date: Mon, 21 Dec 2009 12:54
16 lines
2064 bytes
On 21 Gru, 12:05, Bart Ogryczak <b.ogryc...@gmail.com> wrote:
> On Dec 20, 10:10 pm, Michal M <mmier...@tycowaterworks.pl> wrote:
>
> >  Tym razem podam dokładnie przykład.
>
> Ok, to co tak naprawdę robisz:
>
> >>> m1 = {'log': None}
> >>> m2 = {'Log': 'klasa Log'}
> >>> m4 = {'log': m1['log']}
> >>> m1['log'] = m2['Log']
> >>> m1, m2, m4
>
> ({'log': 'klasa Log'}, {'Log': 'klasa Log'}, {'log': None})

Prosto, zwięźle i jasno. Nic dodać, nic ująć. Dziękuję. :)
Re: Python i importowanie
#27073
Author: Michal M
Date: Sun, 10 Jan 2010 14:53
65 lines
2916 bytes
Siedzę w tym Pythonie już jakiś czas i niestety co chwilę stwierdzam,
że to importowanie jest zdrowo po....

przykład:

p1.m2
----------
import m1
import p2.m3

print m1.A.counter
a = m1.A()
print m1.A.counter
p2.m3.get()

p1.m1
---------
class A(object):
    counter = 0
    def __init__(self):
        A.counter = 1

p2.m3
---------
import p1.m1

def get():
    print "w def m3: " + str(p1.m1.A.counter)


Po uruchomieniu m2:
0
1
w def m3: 0

Długo kombinowałem jak sprawić aby w m3 widział obiekt A taki jakim
jest naprawdę. i w końcu wyszło, że trzeba przerobić m2:

p1.m2
---------

import p1.m1
import p2.m3

print p1.m1.A.counter
a = p1.m1.A()
print p1.m1.A.counter
p2.m3.get()


Teraz wynik jak oczekiwano:
0
1
w def m3: 1

Tylko, że przy pisaniu większego programu z setkami modułów
rozrzuconych po różnych paczkach to staje się horrorem. Już teraz ok.
80% czasu zajmuje mi kombinowanie z importowaniem aby wszędzie było
widziane to co ma być. Już nie mówię o zmorze cyklicznych odwołań
pomiędzy modułami.

Jest na to jakiś sposób, żeby to opanować?
Jakieś rady?
Tak, próbowałem i ciągle próbuję to zrozumieć ale co chwila się łapie
na tym, że już mi się wydawało, że wszystko ok i znowu coś nie działa.
Re: Python i importowanie
#27074
Author: Łukasz Rekucki
Date: Sun, 10 Jan 2010 16:06
69 lines
3493 bytes
On Jan 10, 3:53 pm, Michal M <mmier...@tycowaterworks.pl> wrote:
> Siedzę w tym Pythonie już jakiś czas i niestety co chwilę stwierdzam,
> że to importowanie jest zdrowo po....
>
> przykład:
>
> p1.m2
> ----------
> import m1
> import p2.m3
>
> print m1.A.counter
> a = m1.A()
> print m1.A.counter
> p2.m3.get()
>
> p1.m1
> ---------
> class A(object):
>     counter = 0
>     def __init__(self):
>         A.counter = 1
>
> p2.m3
> ---------
> import p1.m1
>
> def get():
>     print "w def m3: " + str(p1.m1.A.counter)
>
> Po uruchomieniu m2:
> 0
> 1
> w def m3: 0
>
> Długo kombinowałem jak sprawić aby w m3 widział obiekt A taki jakim
> jest naprawdę. i w końcu wyszło, że trzeba przerobić m2:
>
> p1.m2
> ---------
>
> import p1.m1
> import p2.m3
>
> print p1.m1.A.counter
> a = p1.m1.A()
> print p1.m1.A.counter
> p2.m3.get()
>
> Teraz wynik jak oczekiwano:
> 0
> 1
> w def m3: 1
>
> Tylko, że przy pisaniu większego programu z setkami modułów
> rozrzuconych po różnych paczkach to staje się horrorem. Już teraz ok.
> 80% czasu zajmuje mi kombinowanie z importowaniem aby wszędzie było
> widziane to co ma być. Już nie mówię o zmorze cyklicznych odwołań
> pomiędzy modułami.
>
> Jest na to jakiś sposób, żeby to opanować?
> Jakieś rady?
> Tak, próbowałem i ciągle próbuję to zrozumieć ale co chwila się łapie
> na tym, że już mi się wydawało, że wszystko ok i znowu coś nie działa.
Jeśli masz moduł p1.m2 i chcesz zaimportować moduł p1.m1, to
powinieneś zawsze pisać "import p1.m1". To, że "import m1" w ogóle
działa, to jest efekt uboczny i takie zachowanie jest "Deprecated". W
py3k w ogóle nie znalazł by takiego modułu. W 99% przypadków jeśli
twój program wymaga cyklicznych odwołań, to jest z nim coś nie tak.
Re: Python i importowanie
#27075
Author: Bart Ogryczak
Date: Mon, 11 Jan 2010 12:38
91 lines
3652 bytes
On Jan 10, 3:53 pm, Michal M <mmier...@tycowaterworks.pl> wrote:
> Siedzę w tym Pythonie już jakiś czas i niestety co chwilę stwierdzam,
> że to importowanie jest zdrowo po....
>
> przykład:
>
> p1.m2
> ----------
> import m1
> import p2.m3
>
> print m1.A.counter
> a = m1.A()
> print m1.A.counter
> p2.m3.get()
>
> p1.m1
> ---------
> class A(object):
>     counter = 0
>     def __init__(self):
>         A.counter = 1
>
> p2.m3
> ---------
> import p1.m1
>
> def get():
>     print "w def m3: " + str(p1.m1.A.counter)
>
> Po uruchomieniu m2:
> 0
> 1
> w def m3: 0
>
> Długo kombinowałem jak sprawić aby w m3 widział obiekt A taki jakim
> jest naprawdę. i w końcu wyszło, że trzeba przerobić m2:
>
> p1.m2
> ---------
>
> import p1.m1
> import p2.m3
>
> print p1.m1.A.counter
> a = p1.m1.A()
> print p1.m1.A.counter
> p2.m3.get()
>
> Teraz wynik jak oczekiwano:
> 0
> 1
> w def m3: 1
>
> Tylko, że przy pisaniu większego programu z setkami modułów
> rozrzuconych po różnych paczkach to staje się horrorem. Już teraz ok.
> 80% czasu zajmuje mi kombinowanie z importowaniem aby wszędzie było
> widziane to co ma być. Już nie mówię o zmorze cyklicznych odwołań
> pomiędzy modułami.
>
> Jest na to jakiś sposób, żeby to opanować?
> Jakieś rady?
> Tak, próbowałem i ciągle próbuję to zrozumieć ale co chwila się łapie
> na tym, że już mi się wydawało, że wszystko ok i znowu coś nie działa.

Coś jest totalnie nie tak z architekturą twoich modułów.
Ja bym zrobił na przykład tak:

p2.m3
---------

class A:
   """abstrakcyjna klasa do nadpisania przez inny moduł"
   __init__():
       raise NotImplementedError

def get():
     counter = A()
     print "w def m3: " + str(counter)

p1.m2
----------
import m1
import p2.m3

print m1.A.counter
a = m1.A()
print m1.A.counter

p2.m3.A = m1.A
p2.m3.get()
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