Найти - Пользователи
Полная версия: Говнокод. Научите изяществу
Начало » Python для новичков » Говнокод. Научите изяществу
1 2 3 4 5
irgit
Друзья. Только недавно начал писать, поэтому методы превращаются в говнокод. Научите пожалуйста, с самого начала - писать изящно и красиво. Если не сложно, покажите более правильную реализацию, укажите ошибки, например этого кода (https://github.com/tarbagan/vk_parse_group_inregion/blob/master/vk_get_group.py):


 #!/usr/bin/python
# -*- coding: utf-8 -*-
from urllib.request import urlopen
from urllib.parse   import quote
import json
import time
import csv
q = quote("Поисковый запрос") #Например Новости. Можно поставить пробел " ", тогда найдет все группы у которых не менее двух слов
token = "TOKEN"
def get_multicity(): #Получаем населенные пункты вашего региона. Вместо 1157049& укажите свой индификатор региона ВК
    url = "https://api.vk.com/method/database.getCities.json?region_id=1157049&country_id=1&count=200&access_token=" + token + "&v=5.52"
    response = urlopen(url)
    data = response.read()
    city = json.loads(data)
    return city
def multi_search():
    gr = []
    for st in get_multicity()["response"]["items"]:
        stid = str((st["id"]))
        namecity = str((st["title"]))
        url2 = "https://api.vk.com/method/groups.search.json?q="+q+"&city_id="+stid+"&count=1000&sort=0&access_token="+ token +"&v=5.52"
        response2 = urlopen(url2)
        data2 = response2.read()
        group = json.loads(data2)
        time.sleep(0.5)
        if group ["response"]["count"] !=0:
            for pars in group["response"]["items"]:
                pars['city'] = namecity
                grid = str(pars['id'])
                print( "Получаем: %s" % namecity )
                url3 = "https://api.vk.com/method/groups.getMembers.json?group_id="+grid+"&access_token=" + token + "&v=5.52"
                response3 = urlopen(url3)
                data3 = response3.read()
                folower = json.loads(data3)
                fl = (folower["response"]["count"])
                pars['follower'] = fl
                pars['url'] = (str("https://vk.com/club"+grid))
                gr.append(pars)
                time.sleep(0.5)
    return gr
def save_cvs(): #Сохраняем результат в файл CVS
    datagroup = multi_search()
    with open( "d:/AnacodaProgect/group.csv", "w", encoding='utf-8' ) as file: #Укажите путь к ашему файлу cvs
        fieldnames = ['id', 'name', 'is_closed', 'type', 'photo_200', 'city', 'follower', 'url']
        writer = csv.DictWriter( file, fieldnames=fieldnames )
        writer.writeheader()
        for sgroup in datagroup:
            idg = (sgroup["id"])
            nmg = (sgroup["name"])
            icg = (sgroup["is_closed"])
            tyg = (sgroup["type"])
            phg = (sgroup["photo_200"])
            cig = (sgroup["city"])
            flg = (sgroup["follower"])
            urg = (sgroup["url"])
            writer.writerow({'id': idg, 'name': nmg, 'is_closed': icg, 'type': tyg, 'photo_200': phg, 'city': cig, 'follower': flg, 'url': urg} )
save_cvs()
print ("ok")
py.user.next
irgit
 def save_cvs(): #Сохраняем результат в файл CVS
CSV - comma separated values

irgit
Научите пожалуйста, с самого начала - писать изящно и красиво.
Нельзя быстро научиться. Нужно планомерно читать хорошие книги одну за одной, там будет много кодов в правильном виде. Их стиль и будешь копировать, пока он не усвоится. Чем больше будешь писать, тем он легче будет писаться. А потом ты вообще забудешь, что ты научился писать код, тебе будет казаться, что ты с рождения его умеешь писать. Как мы книжки читаем - нам кажется, что мы эти буквы, которые видим, всегда знали. Мы забыли то состояние, когда не знали ни одной буквы.

Что у тебя тут? Глобальная переменная? Значит, ты должен поиметь проблемы из-за глобальных переменных, чтобы для себя самого уяснить, что лучше потрудиться лишний раз и от них полностью избавиться через немогу. То есть для этого тоже нужно мотивацию иметь - знать, что будут вполне конкретные проблемы, если так оставить.

У тебя в коде мало переменных. То есть код пришлёпнут к конкретным каким-то строкам, числам, структурам данных. Стоит только vk.com изменить адресацию у себя внутри, как твой код не только перестанет работать, но и его придётся полностью писать заново, чтобы восстановить. А должно быть так, что формат адреса должен где-то храниться, где его можно быстро поменять и вся программа сразу переключится на новый вид адреса и всё будет работать. Это называется абстрагирование. То есть код должен быть общим, а конкретные детальки должны к нему просто подключаться в одном небольшом месте.

Много книг надо прочитать, причём правильных (есть и водяные книги, где на кучу страниц одна вода бесполезная), в которых всякие технологии программирования раскрываются.
Ты даже если весь Python выучишь наизусть, это тебе ничего не даст, потому что технологии программирования питон тебе не сообщит. Язык не учит программировать. Язык - это просто кисти и краски. А чтобы рисовать картины ими, надо изучать правила и законы изобразительного искусства. Можно кучу кисточек выучить и что дальше? Ничего само не нарисуется.

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


tags: learning
irgit
py.user.next
Нельзя быстро научиться. Нужно планомерно читать хорошие книги одну за одной, там будет много кодов в правильном виде. Их стиль и будешь копировать, пока он не усвоится. Чем больше будешь писать, тем он легче будет писаться. А потом ты вообще забудешь, что ты научился писать код, тебе будет казаться, что ты с рождения его умеешь писать. Как мы книжки читаем - нам кажется, что мы эти буквы, которые видим, всегда знали. Мы забыли то состояние, когда не знали ни одной буквы.

Что у тебя тут? Глобальная переменная? Значит, ты должен поиметь проблемы из-за глобальных переменных, чтобы для себя самого уяснить, что лучше потрудиться лишний раз и от них полностью избавиться через немогу. То есть для этого тоже нужно мотивацию иметь - знать, что будут вполне конкретные проблемы, если так оставить.

У тебя в коде мало переменных. То есть код пришлёпнут к конкретным каким-то строкам, числам, структурам данных. Стоит только vk.com изменить адресацию у себя внутри, как твой код не только перестанет работать, но и его придётся полностью писать заново, чтобы восстановить. А должно быть так, что формат адреса должен где-то храниться, где его можно быстро поменять и вся программа сразу переключится на новый вид адреса и всё будет работать. Это называется абстрагирование. То есть код должен быть общим, а конкретные детальки должны к нему просто подключаться в одном небольшом месте.

Много книг надо прочитать, причём правильных (есть и водяные книги, где на кучу страниц одна вода бесполезная), в которых всякие технологие программирования раскрываются.
Ты даже если весь Python выучишь наизусть, это тебе ничего не даст, потому что технологии программирования питон тебе не сообщит. Язык не учит программировать. Язык - это просто кисти и краски. А чтобы рисовать картины ими, надо изучать правила и законы изобразительного искусства. Можно кучу кисточек выучить и что дальше? Ничего само не нарисуется.

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

Благодарю за ответ, он сподигнул меня на более глубокое осмысление Дзнен. Попробую переписать данный код согласно некой философии структурирования. Что посоветуете почитать?
irgit
 def get_multicity():
    url = "https://api.vk.com/method/database.getCities.json?region_id=1157049&country_id=1&count=200&access_token=" + token + "&v=5.52"
    response = urlopen(url)
    data = response.read()
    city = json.loads(data)
    return city

Подскажите пожалуйста. Этот фрагмент кода лучше записывать как класс (class) или как функцию (def)? Не могу понять, в чем принципиальная разница? Можно ли его упростить? Можно ли его оптимизировать? Как бы его написал гуру питона?
py.user.next
irgit
Этот фрагмент кода лучше записывать как класс (class) или как функцию (def)?
Тут надо сделать подачу ссылки снаружи
 def get_multicity(url):

irgit
Не могу понять, в чем принципиальная разница?
Функция - это алгоритм, принимающий что-то на вход и выдающий что-то на выход.
Объект - это несколько функций, объединённых в группу, которые работают над одним общим набором данных.
Класс - это шаблон для создания объектов.

Например, класс list описывает такие объекты, у которых есть внутреннее содержимое и методы append(), pop(), insert(), которые работают с этим внутренним содержимым.
  
>>> lst = []
>>> lst
[]
>>> lst.append(1)
>>> lst.append(2)
>>> lst.append(3)
>>> lst
[1, 2, 3]
>>> lst.pop()
3
>>> lst.pop()
2
>>> lst.pop()
1
>>> lst
[]
>>>
Таким образом при одном описании класса списка у двух разных объектов-списков, созданных по этому описанию, будет разное внутреннее содержимое. Методы одного списка работают только с его содержимым, а методы другого списка работают только с его содержимым. То есть класс один, а объектов с его помощью можно создавать много и они все будут индивидуальными.

Понятие исполнителя тебе нужно узнать. Это можно прочитать в книжке “Программирование для математиков” Кушниренко-Лебедев

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

Пример исполнителя TwoLists, который хранит внутри себя два исполнителя list и управляет ими таким образом, чтобы перемещать исполнители int из одного в другой.
  
>>> class TwoLists:
...     
...     def __init__(self):
...         self.lst1 = [1, 2, 3]
...         self.lst2 = [4, 5, 6]
...     
...     def move(self):
...         self.lst2.append(self.lst1.pop())
...     
...     def show(self):
...         return self.lst1, self.lst2
... 
>>> two_lists = TwoLists()
>>> 
>>> two_lists.show()
([1, 2, 3], [4, 5, 6])
>>> 
>>> two_lists.move()
>>> two_lists.show()
([1, 2], [4, 5, 6, 3])
>>> 
>>> two_lists.move()
>>> two_lists.show()
([1], [4, 5, 6, 3, 2])
>>>
Исполнитель TwoLists управляет двумя исполнителями list определённым образом, известным только ему. Снаружи, когда мы вызываем методы move() и show(), мы не знаем, что эти методы делают внутри. Также, когда мы используем объект TwoLists, мы не знаем, что внутри TwoLists хранятся исполнители list. В этом фишка исполнителей - они хранят в себе семантику, а наружу предоставляют только интерфейс для управления ими.

Исполнители можно делать разные, с любой семантикой и любыми интерфейсами. Список - хороший, наглядный пример исполнителя. Мы не знаем, как он устроен, но мы можем им пользоваться для выполнения задач. Мы можем поместить в него данные и убрать из него данные, при этом мы не знаем, как он их хранит внутри себя, мы не знаем, какими исполнителями он для этого пользуется внутри себя.

Дерево исполнителей может приводить к очень забубённому поведению, которое сразу так и не осмыслишь. Но при этом можно гарантировать, что всё выполнится ими точно до миллиметра.
PEHDOM
irgit
Подскажите пожалуйста. Этот фрагмент кода лучше записывать как класс (class) или как функцию (def)?
ИМХО класс тут как зайцу пятая нога.
достаточно познавательный перевод статьи, почитайте там как раз по ходу про ваш случай: https://habr.com/post/140581/
Признак того, что объект не должен быть классом — если в нём всего 2 метода, и один из них — инициализация, __init__. Каждый раз видя это, подумайте: «наверное, мне нужна просто одна функция».
vic57
irgit
Можно ли его упростить? Можно ли его оптимизировать?
как коллеги сказали - данные нужно отделять от функции.
и у тебя нет обработки ошибок совсем
примерно так
 import requests
DATA = {}
DATA['req']='https://api.vk.com/method/database.getCities.jsonregion_id=1157049&country_id=1&count=200&access_token='
DATA['token'] = 'TOKEN'
DATA['version'] = '&v=5.52'
def get_multicity(url=None):
    try:
        r = requests.get(url,timeout=5)
    except Exception as e:
        return {'ERROR':str(e)}
    else:
        return r.json()
ret = get_multicity(DATA['req'] + DATA['token'] + DATA['version'])
print(ret)
vic57
можно еще разбить данные на ключи region_id, country_id и т.д. совершенству нет предела
irgit
py.user.next
Понятие исполнителя тебе нужно узнать. Это можно прочитать в книжке “Программирование для математиков” Кушниренко-Лебедев

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

Спасибо! Скачал, читаю Your text to link here…
irgit
PEHDOM
ИМХО класс тут как зайцу пятая нога.
достаточно познавательный перевод статьи, почитайте там как раз по ходу про ваш случай: https://habr.com/post/140581/

Благодарю, увлекательно)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB