Przekazywanie przez referencję

Przekazywanie przez referencję
pieczara
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad rok
0

Cześć,
Jak można przekazać obiekt do funkcji w klasie przez referencję, czy jest to możliwe, nie bardzo mogę znaleźć informacje na ten temat.....
Problem mam taki, że przekazuje instancję obiektu jakiejś własnej klasy do funkcji w celu wykonania operacji na tym obiekcie. Niestety w funkcji pracuję już na innej instancji, tworzy się kopia, sprawdzałem przy pomocy funkcji id(), czy jest jakiś sposób by przekazać go przez referencje, ewentualnie obejście tego progremu?

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:29 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

Możesz pokazać kod? bo to co mówisz kłóci się z moją (niewielką) wiedzą o Pythonie


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:8 minut
4

Niestety w funkcji pracuję już na innej instancji, tworzy się kopia

To raczej nie jest prawda

Patrz:

Kopiuj
>>> class Foo:
...     def __init__(self):
...             self.bar = 'asd'
... 
>>> x = Foo()
>>> x
<__main__.Foo object at 0x7fbfee9ddd30>
>>> x.bar
'asd'
>>> def modify(o):
...     o.bar = 'spam'
... 
>>> modify(x)
>>> x.bar
'spam'

λλλ
edytowany 1x, ostatnio: stivens
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:minuta
  • Postów:4930
2

Modyfikujesz pole obiektu, czyli to do czego wskaźnik się odnosi, ale na stosie jest kopia samego obiektu, (referencji do niego) i jego w funkcji, zmienić nie można; dlatego:

Kopiuj
class Foo:
    def __init__(self):
        self.f = "bar"

def modify(obj):
    obj = "baz"


f1 = Foo()
print(f1)  # -> <__main__.Foo object at 0x7faeac165910>
modify(f1)
print(f1.f, f1) # ->  bar <__main__.Foo object at 0x7faeac165910>

edytowany 1x, ostatnio: lion137
stivens
ale na stosie jest kopia samego obiektu no nie kopia tylko wskaznik na obiekt, ktorego funkcja nie moze zmienic
lion137
Tak, oczywiście, w zasadzie powinienem to dopisać.
stivens
Chyba w dalszym ciagu mowienie o kopii obiektu jest mylace. Proponuje zedytowac tak zeby tylko o tej referencji byla mowa :P
lion137
Dokładniej nie kopia, ale lokalna nazwa, ale juz bym nie dzielił włosa na czworo...
pieczara
  • Rejestracja:ponad 16 lat
  • Ostatnio:ponad rok
0

Jestem początkujący w pythonie i pewnie czegoś nie ogarniam. Staram się zrobić pewien mechanizm, który zrobiłem kiedyś w c c#. W skrócie chodzi o to, by załadować dynamicznie klasy pluginów i uruchomić ich instancje tak, by każda działała w osobnym procesie.

  • każda wtyczka może kręcić się nieskończenie długo i bardzo długo nie zwracać wyniku
  • zinstancjownowane wtyczki znajdują się w tablicy __plugin_instances
  • każda wtyczka dziedziczy po pewnej klasie abstrakcyjnej, która ma zapewnić jednolity interfejs (metody init() i run())

W momencie uruchomienia funkcji run_all_by_configuration tablica instancji jest przekazywana do ProcessPoolExecutor, który przy pomocy funkcji launch_plugin uruchamia procesy - w tej funkcji plugin ma już inne id, następnie w uruchamianej cyklicznie funkcji check_plugins() chce kontrolować stan wtyczek ale widzę, że obiekty w __plugin_instances się nie zmieniają. Zakładam, że coś robię nie tak

screenshot-20210217141658.png

Kopiuj
class InterfaceManager:
    __plugin_loader: PluginLoader
    __pool_executor: concurrent.futures.ProcessPoolExecutor
    __scheduler: sched.scheduler
    __configuration_tree: []
    __plugin_instances: []
    __workers_number: int
    __scheduler_delay: int

    def __init__(self, configuration_tree):
        self.__plugin_loader = PluginLoader(Parameters.inrastructure_plugins_dir)
        self.__configuration_tree = configuration_tree
        self.__workers_number = len(configuration_tree)
        self.__pool_executor = concurrent.futures.ProcessPoolExecutor(max_workers=self.__workers_number)
        self.__plugin_loader.load_all_plugins()
        self.__scheduler = sched.scheduler(time.time, time.sleep)
        self.__scheduler_delay = Parameters.scheduler_delay_for_im

    def verify_configuration(self) -> bool:
        p_i = [x for x in self.__configuration_tree if
               x.enabled == 1 and
               x.plugin_type.processing_type == Enums.ProcessingType.PROCESSING.value and
               x.plugin_type.manager_type == Enums.ManagerType.INTERFACE.value
               ]
        self.__configuration_tree = p_i

        if len(self.__configuration_tree) > 0:
            return True
        else:
            return False

    def init_by_configuration(self):
        self.__plugin_instances = []
        for conf in self.__configuration_tree:
            pl = self.__plugin_loader.plugins[conf.plugin_type.library_name]
            plugin = pl()
            plugin.init(conf.name, conf.plugin_instance_configurations)
            self.__plugin_instances.append(plugin)
            # print(id(plugin))

    def run_all_by_configuration(self):
        if len(self.__plugin_instances) > 0:
            self.__pool_executor.map(self.launch_plugin, self.__plugin_instances)

        self.__scheduler.enter(self.__scheduler_delay, 1, self.__check_plugins)
        self.__scheduler.run()

    def run_single(self):
        pass

    def __check_plugins(self):
        for plugin_instance in self.__plugin_instances:
            print(id(plugin_instance))
            print('Status dla %s - %s', plugin_instance.instance_name, plugin_instance.is_working)

            # print(dir(plugin_instance))
            # print(id(plugin_instance))

        self.__scheduler.enter(self.__scheduler_delay, 1, self.__check_plugins)

    @classmethod
    def launch_plugin(cls, plugin):  # todo: try catch
        print(id(plugin))
        plugin.run()
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:2 dni
  • Lokalizacja:Kraków
  • Postów:2000
2

Jeśli modyfikujesz obiekty w innych procesach, to problem nie leży w przekazywaniu ich do funkcji ;)

Co do zasady procesy nie współdzielą pamięci, każdy będzie miał własną kopię tych obiektów w zaalokowanej dla siebie pamięci i tak dalej.

Co prawda powinno dać się to "ohakować", stosując pamięć współdzieloną - ale wtedy musisz mieć pewność, że procesy z puli będą z niej korzystały i te obiekty musiałyby żyć w pamięci współdzielonej właśnie. Pamiętam, że kiedyś coś takiego robiłem, bo FileLocki sprawiały za dużo problemów, a Pythonowe read/write-locki działały tylko na wątkach. Więc właśnie w oparciu o shared mem wyrzeźbiłem prosty RWLock działający z procesami, także dać się da ;)

https://docs.python.org/3/library/multiprocessing.shared_memory.html
https://stackoverflow.com/a/14135569


edytowany 1x, ostatnio: superdurszlak
stivens
Z ciekawosci, jak w Pythonie zrobic taka pamiec wspoldzielona? W C bym potrafil ale w Pythonie nie :P
superdurszlak
W sumie bardzo słabo pamiętam. Wydaje mi się, że ja to wtedy obszedłem w dość brzydki sposób, wykorzystując ładowanie modułów do tej pamięci :]
koszalek-opalek
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 2 lata
1

Tak dla uporządkowania -- w Pythonie wszystko jest przekazywane przez wskaźnik, nie ma przekazywania przez referencję (przynajmniej tak, jak to się rozumie np. w C++).

A więc nie możemy zmienić przekazanego obiektu na inny, ale możemy zmienić jego zawartość...

PI
No to tak się zachowują referencje c++ To takie stałe wskaźniki ;-)
koszalek-opalek
@pitgal: Nie, w Pythonie mamy inne zachowanie -- a referencje bliskie są stałym wskaźnikom, ale nie tożsame jednak...
PI
No racja różnią się uproszczoną składnią bez potrzeby używania ->

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.