Python3.x self как параметр в вызове метода для другого класса - PullRequest
0 голосов
/ 18 февраля 2019

Я пытаюсь вызвать метод другого класса и дать вызываемому классу ссылку на текущий класс вместе с некоторыми другими параметрами.Но каким-то образом он принимает себя, заданный в качестве параметра, как себя вызываемого класса.

Позвольте мне показать вам:

import os, sys
from wsPart import wsPart
class thermo(wsPart):
    functional = False ## see line 8
    file = '/sys/bus/w1/devices/28-00000833e8ff/w1_slave' 
    def __init__(self, name, logger):
        super().__init__(name, logger)
        functional = True 
    def read(self):
        fileobject = open(self.file)
        filecontent = fileobject.read()
        fileobject.close()
        self.logger.writeLog(self,"Completed Meassurement") ##Problem on this line
        return filecontent

Поэтому я называю класс logger и метод writeLog на это.Предоставление сообщения Parameters и ссылки на класс therm (self).

import datetime
from wsPart import wsPart
class logger():
    logfile = "/var/log/wheaterstation.log"
    name = "Logger"
    def writeLog(self, sender, message):
        conn = open(self.logfile, "w")
        now = str(datetime.datetime.now().isoformat())
        conn.write("[" + now + "]" + " (" + sender.getName() + "): " + message + "\n") ##Problem on this line
        conn.close()

Как вы можете видеть, я поставил параметры self, поскольку метод, принадлежащий классу, должен senderбыть ссылкой на класс термо, который был передан как сам в классе термо.Наконец, есть также message, который был также передан в классе термо.Но это просто дает мне ошибку:

Traceback (most recent call last):
File "scrLib/wsControl.py", line 61, in <module>
controller = controller()
File "scrLib/wsControl.py", line 22, in __init__
self.thermo = thermo("Thermometer", logger)
File "/home/joco/git/wheaterstation/scrLib/thermo.py", line 10, in __init__
super().__init__(name, logger)
File "/home/joco/git/wheaterstation/scrLib/wsPart.py", line 8, in __init__
self.logger.writeLog(self, "created")
TypeError: writeLog() missing 1 required positional argument: 'message'

Таким образом, кажется, что параметр self, который был передан в термо классе, интерпретируется как self класса logger, который получает все этоперепутал.

Можете ли вы, ребята, помочь мне здесь?

Спасибо всем заранее

Полный код + дополнительные комментарии можно посмотреть Здесь

Редактировать: И логгер и термо класс инициализируются в файле wsPart.py:

class controller():
    name = ""
    logger = None
    thermo = None
    dbConnector = None

    def __init__(self):
    ##THis created the controller and all the other objects
        self.name = "Controller"
        ##Create Objects
        self.logger = logger()
        self.logger.writeLog(self,"logger created") ##This line Works
        self.thermo = thermo("Thermometer", logger)
        self.dbConnector = dbConnector("DBConnector",logger)

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Абсолютно не связано, но код в комментариях не читается, поэтому я выкладываю это как ответ:

  1. это не работает, как вы, вероятно, ожидаете:

    класс Что угодно (): functions = False ## см. строку 8

    def __init__(self, name, logger):
        super().__init__(name, logger)
        functional = True 
    

Python не имеет значения «подразумевал это» здесь, в __init__ вы создаете не атрибут экземпляра, а локальную переменную,Вы хотите self.functional = True

Убедитесь, что вы закрыли файлы

def read (self): fileobject = open (self.file) filecontent = fileobject.read () fileobject.close ()

Если между open() и fileobject.close() произойдет что-то неправильное, файл не гарантированно будет закрыт должным образом.Вам нужен блок try/finally, т. Е.

    f = open(path)
    try:
        do_something_with(f)
    finally:
        f.close()

или, что еще лучше, блок with:

    with open(path) as f:
        do_something_with(f)

, который обеспечит закрытие файла в любом случае.

write режим усекает файл

def writeLog (self, sender, message): conn = open (self.logfile, "w") now = str (datetime.datetime.now() .isoformat ()) conn.write ("[" + now + "]" + "(" + sender.getName () + "):" + message + "\ n") ## Проблема в этой строке conn.close ()

как задокументировано , открытие файла в режиме записи усекает файл.Вам, вероятно, нужен режим «добавления» вместо этого.

Не изобретайте колесо прямоугольной формы, когда оно уже круглое

Ведение журнала не так тривиально, как просто запись в файл (проблемы параллелизма, необходимо отправить сообщение журнала в другое место назначения, ведение журналов и т. д.), и даже если вам не нужно больше (по крайней мере, на данный момент), ваше решение довольно неэффективно (открытие файла стоит дорого).

Python имеет очень полный пакет журналирования в своей стандартной lib.Я полностью согласен с тем, что для правильной настройки и использования требуется некоторое обучение, но это все еще огромная победа по сравнению с тем временем, которое вы потратите, пытаясь заставить наивную полуобеспеченную пользовательскую реализацию правильно работать на производстве, и это знание того, чтов любом случае вам понадобится любой серьезный проект.

0 голосов
/ 18 февраля 2019

да, плохая идея называть экземпляр и имя класса одинаковыми.Здесь:

    self.logger = logger()
    self.logger.writeLog(self,"logger created") ##This line Works
    self.thermo = thermo("Thermometer", logger)
    self.dbConnector = dbConnector("DBConnector",logger)

Вы передаете класс своим конструкторам.Таким образом, методы рассматриваются как статические / ожидают еще один параметр.Вам нужно изменить 2 последние строки, чтобы передать только что созданный экземпляр:

    self.thermo = thermo("Thermometer", self.logger)
    self.dbConnector = dbConnector("DBConnector", self.logger)

, что более важно, вам нужно использовать разные имена для классов и экземпляров одних и тех же объектов, чтобы избежать этой путаницы (соглашение Python дляИмена классов начинаются с каждого слова в верхнем регистре (верблюд), например: Logger. Другие языки не используют это соглашение, но Python очень много о соглашениях).

С другим именем, которое у вас будетВы получили исключение NameError, и вы бы исправили ошибку самостоятельно.

Кроме того: не "инициализируйте" такие члены в определении класса:

name = ""
logger = None
thermo = None
dbConnector = None

те, кто создает классчлены, а не члены экземпляра.Удалите их и позвольте __init__ создавать элементы экземпляра, как вы делаете сейчас.__init__ называется независимо от того, что, и эти строки просто добавляют путаницу (за исключением некоторых угловых случаев, только константы должны быть объявлены таким образом)

...