LINUX.ORG.RU

маленький вопрос по Python

 


0

2

Приветствую, ситуация значит следующая, есть некий базовый класс с несколькими переменными-членами(типа общими для всех потомков) и несколько наследованных от него потомков. К потомках есть метод save, который возвращает строчку со значением всех переменных класса: Примерно так:

class Primitive:
    def __init__(self):
        self.type       = None
        self.thickness  = 1
        self.color      = "#000000"

    def save(self):
        pass
    
    def load(self, values):
        pass


class Line(Primitive):
    def __init__(self):
        self.x1 = 0
        self.x2 = 0
        self.y1 = 0
        self.y2 = 0

    def save(self):
        return  self.__class__.__name__ + " " +\
                str(self.x1)            + " " +\
                str(self.y1)            + " " +\
                str(self.x2)            + " " +\
                str(self.y2)            + " " +\
                str(super(Line, self).color)   # <---- ? как обратиться к родителю, чтобы подтянуть значения эго перемнных

    def load(self):
        pass

if __name__ == "__main__":
    line = Line()
    print line.save()

Но возникает вопрос, как из потомка обратиться к родителю, чтобы получить значения его переменных? Т.е на выходе должно быть что-то вроде:

Line 10 10 50 50 line 1 #ff0000
★★★★★

Последнее исправление: xterro (всего исправлений: 1)
Ответ на: комментарий от Mahmood

У меня нет пробелов после открывающей скобки, перед закрывающей есть. И пример как-то не очень подходит.
Дай Б*Г этому PEP долгие лета, но, как по мне, чистая вкусовщина такие требования.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Я предлагал для улучшения читаемости ставить не две скобки подряд, а через пробел: ( (a, b) ) vs ((a, b)). Хотя со списком действительно выглядит лучше.

Mahmood
()

как-то так. И не забывай инициализировать базовый класс в наследнике)

class Primitive: def __init__(self): self.type = None self.thickness = 1 self.color = «#000000»

def save(self): pass def load(self, values): pass

class Line(Primitive): def __init__(self): self.x1 = 0 self.x2 = 0 self.y1 = 0 self.y2 = 0 Primitive.__init__(self)

def save(self): for name in dir(self): print name, getattr(self, name)

if __name__ == '__main__': Line().save()

fancymash
()
Ответ на: комментарий от menangen

забудь о наследовании класса от object, по сути это - костыль.

Это вы что тут за бредятину сейчас задвинули?)

anonymous
()
Ответ на: комментарий от anonymous

Да вот, ищу способ как привлечь анонимусов в тему, вроде, работает!

menangen ★★★★★
()
Ответ на: комментарий от i-rinat

Пффффф!... ты сам придумаешь бенчмарк, который покажет обратный результат (и про сложение строк, и про скорость pypy) и при этом имеет большую практическую ценность, или тебе помочь?..

ei-grad ★★★★★
()
Последнее исправление: ei-grad (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Иногда лучше прислушаться к здравому смыслу и чужому опыту, чем придумывать свои бенчмарки.

ei-grad ★★★★★
()
Ответ на: комментарий от fancymash

— Алло, это конкурс вредных советов?

Зачем инициализировать базовый класс в конце __init__ наследника? Чтобы иметь возможность затереть его поля одноименными родительскими?

Virtuos86 ★★★★★
()
Ответ на: комментарий от i-rinat

Ребята, раз в тут батл ведёте, спрошу ещё один момент, есть ли красивое решение, для загрузки значений аргументов класса в цикле, типа:

 # на входе типа: line 0 0 0 0 1 #000000 0 0
 def load(self, values):
        if values is not None:
            vlist = values.split(" ")
            print vlist
            print self.__dict__
            if vlist[0].lower() == self.__class__.__name__.lower():
                for item in vlist[1:]:
                    pass  

Можно ли как-нибудь пройти по self.__dict__ в порядке, в котором переменные определены в классе(в этом порядке в строке values определены значения), чтобы присвоить им значения?

xterro ★★★★★
() автор топика
Последнее исправление: xterro (всего исправлений: 1)
Ответ на: комментарий от xterro

батл ведёте

Да какой тут батл, мне просто все объясняют, что я не прав. Только почему-то без конкретики. Просто не прав, во всём.

Можно ли как-нибудь пройти по self.__dict__ в порядке, в котором переменные определены в классе

Словарь не сохраняет порядок. Есть https://docs.python.org/2/library/collections.html#collections.OrderedDict, но это всё равно не то, что тебе нужно. А нужен тебе, как аноним уже сказал, pickle. Старайся не использовать pickle на данных, которые пришли извне. Если надо обмениваться данными, бери json/bson.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat
→ python test.py 
-----
plusplus  0.16966358900003797
jointuple 0.1703812140001446
joinlist  0.1644105989998934
-----
plusplus  0.1657785849999982
jointuple 0.16506740700015143
joinlist  0.16508353599988368
-----
plusplus  0.1654957429998376
jointuple 0.1666055690000121
joinlist  0.1653377499999351
[ ei-grad@yoga-s1 ~ ]
→ pypy test.py  
-----
plusplus  1.58733201027
jointuple 0.373677015305
joinlist  0.370100021362
-----
plusplus  1.57707691193
jointuple 0.371634960175
joinlist  0.37503695488
-----
plusplus  1.57512187958
jointuple 0.371918916702
joinlist  0.372656822205
[ ei-grad@yoga-s1 ~ ]
→ cat test.py
from functools import partial
from timeit import timeit


number = 50


s1 = "He" * 1000000
s2 = "ll" * 1000000
s3 = "o," * 1000000
s4 = " W" * 1000000
s5 = "or" * 1000000
s6 = "ld" * 1000000
s7 = "!" * 10000000


def plusplus(s1, s2, s3, s4, s5, s6, s7):
    return s1 + " " + s2 + " " + s3 + " " + s4 + " " + s5 + " " + s6 + " " + s7


def jointuple(s1, s2, s3, s4, s5, s6, s7):
    return " ".join((s1,s2,s3,s4,s5,s6,s7))


def joinlist(s1, s2, s3, s4, s5, s6, s7):
    return " ".join([s1,s2,s3,s4,s5,s6,s7])


for i in range(3):
    print("-----")
    print("plusplus  " + str(timeit(partial(plusplus, s1, s2, s3, s4, s5, s6, s7), number=number)))
    print("jointuple " + str(timeit(partial(jointuple, s1, s2, s3, s4, s5, s6, s7), number=number)))
    print("joinlist  " + str(timeit(partial(joinlist, s1, s2, s3, s4, s5, s6, s7), number=number)))
ei-grad ★★★★★
()
Ответ на: комментарий от ei-grad

Да, на python2 str.__add__ таки быстрее почему-то:

→ python2 test.py
-----
plusplus  0.149036884308
jointuple 0.173014879227
joinlist  0.169308900833
-----
plusplus  0.143420934677
jointuple 0.169507026672
joinlist  0.168989896774
-----
plusplus  0.143234014511
jointuple 0.173110961914
joinlist  0.169274091721
ei-grad ★★★★★
()
Ответ на: комментарий от ei-grad

Спрятал оверхед за двухмегабайтными строками. Молодец, чо.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

pypy со своим jit хуже работает с памятью, ну и в замыкании ему сложнее оптимизировать до выдачи константы сложение переданных переменных, чем сложение неизменяющихся переменных из globals

ei-grad ★★★★★
()
Ответ на: комментарий от ei-grad

ну и в замыкании ему сложнее оптимизировать до выдачи константы сложение переданных переменных, чем сложение неизменяющихся переменных из globals

Уменьши длину строк в своём примере и увеличь число циклов, а потом прогони через pypy ещё раз.

i-rinat ★★★★★
()

ei-grad, i-rinat, подскажите что почитать по этой теме. На данный момент прочитана книга Лутца «Изучаем Python», но есть некоторые моменты по классам, которые без практики забылись, буду перечитывать и пытаться найти им применение, чтобы закрепить практикой. В этой книге оптимизации не уделялось внимание, только приводилось несколько примеров, где производительность изменилась при переходе 2->3 с оговоркой, что такие изменения могут периодически происходить в разных местах в рамках третьей версии. На очереди книга того же автора «Программирование на Python». Чувствую, что еще месяца на 4 чтивом я буду обеспечен. Но от дополнительных материалов не откажусь. Спасибо.

anonymous
()
Ответ на: комментарий от xterro

Только если парсить исходник. Но это и ненужно:

for k, v in zip('a b c'.split(), values.split()):
    setattr(self, k, v)

Дл вывода кстати

print '%(a)s %(b)s %(c)s'%self.__dict__

AIv ★★★★★
()
Ответ на: комментарий от i-rinat

Хм. Ок... сложить короткие строки и правда дешевле чем сформировать список.

→ pypy test.py
-----
plusplus  0.061408
jointuple 0.903238
joinlist  1.311616
-----
plusplus  0.055086
jointuple 0.895155
joinlist  1.307524
-----
plusplus  0.055048
jointuple 0.895060
joinlist  1.308354
ei-grad ★★★★★
()
Ответ на: комментарий от anonymous

Мои знания Python поверхностные, кроме tutorial'а на официальном сайте, я ничего не читал, так что посоветовать ничего не могу. IMHO, если дело дошло до микрооптимизаций в программах на скриптовых языках, то где-то по пути был поворот не туда. Но если всё же припёрло, стоит делать бенчмарки, и именно того кода, который оптимизируется.

С недавних пор уведомления от упоминания анонимом не приходят.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

ещё такая зачётная штука есть

>>> import dis
>>> dis.dis('" ".join([s1,s2,s3,s4,s5,s6,s7])')
  1           0 LOAD_CONST               0 (' ')
              3 LOAD_ATTR                0 (join)
              6 LOAD_NAME                1 (s1)
              9 LOAD_NAME                2 (s2)
             12 LOAD_NAME                3 (s3)
             15 LOAD_NAME                4 (s4)
             18 LOAD_NAME                5 (s5)
             21 LOAD_NAME                6 (s6)
             24 LOAD_NAME                7 (s7)
             27 BUILD_LIST               7
             30 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             33 RETURN_VALUE

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.