LINUX.ORG.RU

[python] Как написать понятный код

 


0

4

Здравствуйте.
С недавних пор увлекся питоном и честно сказать после джавы он выглядит очень странно
С самим с синтаксисом я разобрался, но все что я на нем пишу выглядит как говно.
Хочу понять что я неправильно делаю
Простой пример, пытался написать xml парсер, взял либу lxml и xml'ку следующего вида

<root>
	<server>s1</server>
	<login>test_login</login>
	<password>qwerty</password>
	
	<buildings ai="true">
		<building id="" type="" />
		<building id="3" type="" />
		<building id="5" type="" />
	</buildings>
</root>
Вроде бы все просто, есть какой то заголовок и в нем содержится список.
А вот что у меня получилось на питоне:
from lxml import etree
from common import SimpleEnum

TAG_TYPE = SimpleEnum(('TEXT', 'BUILDING'))

class Buildings:
    def __init__(self):
        self.ai = None
        self.building = []
        
    def __str__(self):
        return 'ai: ' + str(self.ai) + '; building: ' + str(self.building)
        
    
class Building:
    def __init__(self):
        self.id = None
        
    def __str__(self):
        return 'id: ' + self.id


class Config():
    def __init__(self):
        self.parse()
    
    def find(self, tag_name, type = TAG_TYPE.TEXT):
        tag = self.doc.find(tag_name)
        if tag is not None:
            if type ==  TAG_TYPE.TEXT:
                text = tag.text
                if text:
                    return text
                else:
                    raise ValueError('Тег: ' + tag_name + 'найден, но не имеет значений')
            elif type == TAG_TYPE.BUILDING:
                return self.parse_buildings(tag)
            
        else:
            raise ValueError('Не найден тег: ' + tag_name)
        
    def parse_buildings(self, tag):
        buildings = Buildings()
        ai = tag.get('ai')
        buildings.ai = False if ai is not None and 'FALSE' == ai.upper() else True
        buildings.building = []
        for building_tag in tag.findall('building'):
            building = Building()
            if building_tag.get('id'):
                building.id = building_tag.get('id')
            buildings.building.append(building)
        return buildings
                
        
    def parse(self):
        self.doc = etree.parse('config.xml')
        self.server = self.find('server')
        self.login = self.find('login')
        self.password = self.find('password')
        self.buildings = self.find('buildings', TAG_TYPE.BUILDING)
        
    def __str__(self):
        return 'server: ' + self.server + '; login: ' + self.login + '; password: ' + self.password + \
            '\nbuildings: ' + str(self.buildings)

print(Config())
И мне не понятно как уйти от этой сложности или может на питоне так и должно выглядеть?
Не понятно почему не предусмотрена нормальная конвертация str -> bool, bool -> str, что бы если пишешь bool('false') или bool('true') возвращались false и true.
Не понятно почему я могу расширить сущность бина (Buildings и Building) за его пределами. т.е. я бы мог вообще не писать объявление переменных в методах __init__ а просто написать pass и все равно бы все работало.
Не ясно почему нет такой удобной штуки как enum.
Хочется понять что я делаю не так?


n4ela

Как написать понятный код

Форматирование там весьма определённое. А для больше понятности - пиши комментарии в коде. Нет, правда, я серьёзно.

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

А для больше понятности - пиши комментарии в коде. Нет, правда, я серьёзно.

Чушь. Если питоновский код надо комментировать, то это точно надо переписать.

baverman ★★★
()

Ну а так, за исключением вышеперечисленного идиотизма все норм.

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

А код-то у него как у питонщика! К. О. утверждает, что он у тех питонщиков учится.

Also, «hello world» -
быдлокод-питощиков-версия:

import gtk

class HelloWorldApp():
      def close(self, widget, data=None):
          gtk.main_quit()

      def delete_event(widget, event, data=None):
          print "delete event occurred"
          return False

      def __init__(self):
           self.window = gtk.Window()
           self.window.connect("destroy", self.close)
           self.window.connect("delete_event", self.delete_event)
           self.button = gtk.Button("Hello!")
           self.button.connect("clicked", self.close)
           self.window.add(self.button)
           self.button.show()
           self.window.show()

      def main(self):
           gtk.main()
if __name__ == "__main__":
     app = HelloWorldApp()
     app.main()

И небыдлокод-версия (моя, легко читается и понимается):

import gtk #импортируем библиотеку gtk

def close(widget):
     gtk.main_quit() #или exit() - выход

button = gtk.Button("Hello!") #создаем кнопку с надписью "Hello!", запихиваем ее в переменную button
button.connect("clicked", close) #выполнение close при нажатии на кнопку

window = gtk.Window() #создаем окно, запихиваем его в переменную window
window.connect("destroy", close) #выполнение close при нажатии на кнопку закрыть на коробке окна
window.add(button) #добавить кнопку button на форму

window.show_all() #грузим форму со всеми ее делами
gtk.main() #грузим все это дело

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

+1, никогда не понимал этого задрачивания ооп и налеплевания классов там где это ненужно

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

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

Для более сложного виджета HelloWorldApp нужно просто чуть-чуть расширить, твой же код превратиться в нечитабельную простыню и его придётся рефакторить.

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

Мое мнение увы таково, что этот каркас, равно ООП, не нужен в 99% случаев. Проблема питона в том, что он бывает в нем еще нужен из-за самого питона, хотя в PHP по-прежнему был бы не нужен.

А дальше - приводи примеры (как же именно, например, надо расширять?). Пока что мой код более читаемый.

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

Добавь layout, скажем Grid обычный, и размести на нём с десяток контролов + какие-то обработчики их.

А потом захоти засунуть всё это не в отдельное окно, а в другой layout в качестве контрола. Что ты будешь делать со своей простынёй? Класс может лежать в отдельном модуле и дёрнуть его это обычный import, а что с твоей простынёй будет?

Norgat ★★★★★
()

Я вообще не понял зачем всё так сложно. Неужели нельзя сделать класс, а потом продтись по чилдренам и всё запонить. Тут с SAX или minidom займут с десять строк. Зачем такие кострукции, цель в чем?

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

быдлокод-питощиков-версия:

И небыдлокод-версия (моя, легко читается и понимается):

Эти две версии практически одинаковы, так что если первая - быдлокод, то и вторая тоже. Вот различие быдлокода и нормального кода: [python] Как написать понятный код и [python] Как написать понятный код (комментарий)

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

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

программировать через пару месяцев после написания кода - это, конечно, сильно

а вообще рекомендую обложиться PEP8 + dive into python, до кучи можно почитать google python style

shty ★★★★★
()

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

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

зачем класс buildings, который тупо суть есть список.

Ну ты луддит какой-то. А как же наследование, инкапсуляция, полиморфизм?

ugoday ★★★★★
()

Ты просто мыслишь в терминах Java. И ещё не переключился на Python. А переключишься тогда, когда одна палочка и девять дырочекпитоновский код начнёт оптимизироваться ещё в голове, а код на Java выглядеть всё более странно. И так почти с любыми языками.

blexey ★★★★★
()

У Java и Python разные coding conventions. Мне тоже проблеваться хочется от Python и подчеркивания С++ колят глаза. Привычка

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