Jak bardzo Pythonowy jest mój kod

Odpowiedz Nowy wątek
2015-10-27 21:09
Zielony Python
0

Proszę o ocenę mego kodu, wcześniej kodziłem trochę w C++:

import random
import getpass

rock = "rock"
paper = "paper"
scissors = "scissors"

single_player = "single player"
multiplayer = "multiplayer"

synonyms = {"rock": rock,
            "paper": paper,
            "scissors": scissors,
            "stone": rock,
            "vellum": paper,
            "shears": scissors,
            "kamien": rock,
            "papier": paper,
            "nozyce": scissors,
            "r": rock,
            "p": paper,
            "s": scissors
            }

modes = {"single": single_player,
         "multi": multiplayer,
         "singleplayer": single_player,
         "multiplayer": multiplayer,
         "single player": single_player,
         "s": single_player,
         "m": multiplayer
         }

chosen_single_player = "You Chosen The Game With a Computer" 

chosen_multi_player = "You Chosen The Game With An Another Player"

game_is_draw = "Game is a Draw"

playerA_wins = "Player A Wins"

playerB_wins = "Player B Wins"

transitions = {(null, null): both_players_must_choose,
               (null, rock): playerA_must_choose,
               (null, paper): playerA_must_choose,
               (null, scissors): playerA_must_choose,
               (rock, null): playerB_must_choose,
               (rock, rock): game_is_draw,
               (rock, paper): playerB_wins,
               (rock, scissors): playerA_wins,
               (paper, null): playerB_must_choose,
               (paper, rock): playerA_wins,
               (paper, paper): game_is_draw,
               (paper, scissors): playerB_wins,
               (scissors, null): playerB_must_choose,
               (scissors, rock): playerB_wins,
               (scissors, paper): playerA_wins,
               (scissors, scissors): game_is_draw
               }

playerA_choice = ' '
playerB_choice = ' '
mode_choice = ' '

# Main 
print("You are playing Rock Paper Scisscors")
print("Choose a mode: single player or mutliplayer?" )
while mode_choice not in modes:
    mode_choice = input("Enter The Game Mode: ")

if modes[mode_choice] == single_player:
    while playerA_choice not in synonyms:
        playerA_choice = input("Enter Your Choice: ")

    playerB_choice = random.choice(list(synonyms.keys()))
    #print(playerB_choice)

    print(transitions[synonyms[playerA_choice], synonyms[playerB_choice]])

elif modes[mode_choice] == multiplayer:
    while playerA_choice not in synonyms:
        playerA_choice = getpass.getpass("Player A: Enter Your Choice: ")

    while playerB_choice not in synonyms: 
        playerB_choice = getpass.getpass("Player B: Enter Your Choice: ")

    print("The Player A Choose '{}' And The Player B Choose '{}'".format(playerA_choice, playerB_choice)) 
    print(transitions[synonyms[playerA_choice], synonyms[playerB_choice]])
"playerA_must_choose" --- gdzie deklarujesz te zmienne? Odpala ci się ten kod i nie rzuca błędem? - LukeJL 2015-10-27 21:38
Przecie to nie działa... - Maciej Cąderek 2015-10-27 21:51
przyłączam się do przedmówcy - brakuje wielu zmiennych więc nie można tego uruchomić - furas 2015-10-27 21:59
fakt, przepraszam bardzo. Po prostu przed wrzuceniem tego na forum usunąłem parę opcji (czyt. koncept początkowy zakładał, że można niczego nie wpisać) i nie sprawdziłem tego. Musiałem założyć konto aby tutaj odpowiedzieć. Wystarczy usunąc te zmienne w transitions - jaSwiezak 2015-10-27 22:08

Pozostało 580 znaków

2015-10-27 21:40
Zielony Python
0

"playerA_must_choose" --- gdzie deklarujesz te zmienne? Odpala ci się ten kod i nie rzuca błędem?

Pozostałość po starym koncepcie. Ta opcja nie występuje, nie ma szans jej wywołać.

Pozostało 580 znaków

2015-10-27 22:12
0

Pomijając fakt, że się nie uruchamia bo brak wielu zmiennych:

Z pythonowych rzeczy to bym nazwał dużymi literami stałe,
czyli elementy, którym nie jest zmieniana wartość
np.

ROCK = "rock"
PAPER = "paper"
SCISSORS = "scissors"

Z rzeczy już niepythonowych to zamiast wartości tekstowych
przypisał bym im wartości liczbowe - i tak ich nie wypisujesz
a liczby szybciej komputerowi porównać
choć przy tak małej grze to nie ma takiego znaczenia

ROCK = 1
PAPER = 2
SCISSORS = 3

-

Przy wyborze trybu gry i symbolu wolałbym jednak wybierać cyfrę 1, 2 lub pojedynczyą literę
niż pisać całe słowo więc taka możliwość wydaje mi się zbyteczna.

Pozostało 580 znaków

2015-10-28 03:17
0

Może pisz bardziej obiektowo niż strukturalnie?

Pozostało 580 znaków

2015-10-28 09:56
1

nie widzę ani jednego słowa kluczowego def co dla mnie jest oznaką, że jest bardzo źle (jak używałeś C++ to też musiało być jeszcze bardziej nieczytelnie).


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22, 2015-10-28 09:59

Pozostało 580 znaków

2015-10-28 15:34
6

Wyobraź sobie, że ktoś chciałby użyć np. jakiejś stałej z twojego kodu. Importuje sobie więc: from nazwa_modulu import transitions. Chyba ostatnie, czego w tym momencie się spodziewa, to wyświetlenie dwóch tekstów w konsoli i czekanie na input użytkownika, a tak niestety się dzieje po zaimportowaniu twojego modułu. Żeby się przed tym uchronić otaczamy wykonywalny kod w takiego ifa:

if __name__ == '__main__':
    pass  # wykonywalny kod tutaj

Generalnie robimy tak zawsze, gdy wiemy, że kod może być odpalany bezpośrednio, a nie tylko importowany. Więcej o tym tutaj.

Jak najbardziej zgadzam się z @MarekR22, musisz wydzielić z tego czytelne funkcje. Linijek będzie więcej, ale wracając do tego po kilku miesiącach skumasz znacznie szybciej o co chodzi. Może to nie jest widoczne przy dosyć prostym kodzie, ale kilkanaście linijek więcej i nie wiedziałbyś co się tu dzieje. Staraj się, żeby funkcje miały maksymalnie jeden stopień zagłębienia i były krótkie, a nazwy sensowne. Wtedy taki kod się czyta jak książkę ;)

Natomiast nie zgadzam się ze @Spine, nie widzę tutaj potrzeby wsadzania żadnych klas. Python to nie Java i nie chodzi o to, że nie piszę się w nim obiektowo, tylko, że nie zawsze konieczne jest opakowywanie wszystkiego w to słowo kluczowe, a kod nadal może zostać "obiektowy". W Pythonie moduły są obiektami, więc przestrzeń nazw mamy. Dalej - jako, że instancja gry byłaby i tak singletonem, to na jedno wychodzi, dodalibyśmy po prostu kolejny niepotrzebny poziom pseudo-abstrakcji. W Pythonie nie ma nacisku na enkapsulację, dodanie klasy nic w tym nie zmienia. Wniosek: jest okej. Inna rzecz przy bardziej rozbudowanej grze, gdzie takich obiektów byłoby znacznie więcej, ale nawet wtedy stawiałbym głównie na takie rzeczy jak namedtuple czy słowniki, gdzie tylko się da.

edytowany 1x, ostatnio: Wizzie, 2015-10-28 15:34

Pozostało 580 znaków

2015-10-28 16:21
1

Powtarzająca się logika. Najpierw masz tutaj coś takiego:

 while playerA_choice not in synonyms:
        playerA_choice = getpass.getpass("Player A: Enter Your Choice: ")

a potem prawie to samo, tylko dla gracza B:

    while playerB_choice not in synonyms: 
        playerB_choice = getpass.getpass("Player B: Enter Your Choice: ")

To przeciez można włożyć funkcję (czyli zgadza się to, o czym @MarekR22 mówił, że nie ma żadnej funkcji zdefiniowanej) nazwać np. get_player_choice i wywoływać tak:


get_player_choice(playerB)

nie prościej?

Poza tym... po co playerA, playerB? To nie jest skalowalne, bo 3 gracz już nie dojdzie. Lepiej już zrobić listę graczy, np.

[
{'name': 'Marcin', 'last_choice': None},
{'name': 'Genowefa', 'last_choice': None},
]

(używam literału obiektu dla prostoty, chociaż zapewne taką listę będziesz tworzył inaczej, bardziej dynamicznie, wczytując najpierw od usera liczbę graczy i ich imiona)

Dalej mamy niepotrzebne w tym przypadku rozróżnienie na singleplayer i multiplayer. Są gry, gdzie rozgrywka na jedną osobę i drugą jest zupełnie inna, i takie rozróżnienie miałoby sens. Ale tutaj rozgrywka jest dokładnie taka sama. Ludzie po kolei dokonują wyborów i potem nastąpi przeliczenie punktów.

Więc to zrobiłeś:

if modes[mode_choice] == single_player:
....
elif modes[mode_choice] == multiplayer:

Jest słabe. Z powodu nieumiejętności wydzielenia abstrakcji poszedłeś na łatwiznę i zrobiłeś kopiuj-wklej.

A przecież zobacz. Czym się różni tryb single i multiplayer?
Tylko tym:

 playerB_choice = random.choice(list(synonyms.keys())

A wystarczy, żebyś w danych gracza dodał flagę czy dany gracz jest człowiekiem czy komputerem:

[
{'name': 'Marcin', 'last_choice': None, 'is_human': True }
{'name': 'Genowefa', 'last_choice': None, 'is_human': False},
]

a potem sprawdzać coś w rodzaju tego:

if player['is_human']:
    player['choice'] = get_player_choice(player)
else: 
    player['choice'] = random.choice(list(synonyms.keys())

Podsumując - twój kod jest bardzo imperatywny, brak większych abstrakcji, dużo powtórzeń tych samych idiomów etc.
Bardziej jakbyś w assemblerze pisał, niż w pythonie... ;)

Tym niemniej wydaje mi się, że pytanie jest źle zadane. Nie jest kwestia tego, czy kod jest pythonowy czy nie, tylko raczej czy umiesz dostrzec i zaimplementować odpowiednie abstrakcje. Ale to można ćwiczyć. Tylko trzeba zwracać uwagę na

  • elastyczność programu (twój program nie jest elastyczny, bo 3 gracz nie dojdzie)

  • prostotę kodu (twój program nie jest prosty, bo powtarzasz to samo dla trybu single i multi, zamiast mieć w jednym miejscu tę logikę)

  • czytelność (twój kod przez to, że nie ma żadnych abstrakcji tylko ciurkiem wszystko leci zbyt czytelny nie jest).

  • strukturę danych / model (Tutaj o ile częściowo o tym myślałeś (transitions) to np. o tym, żeby wsadzić dane gracza w jakiś słownik, obiekt czy jakąkolwiek inną strukturę danych (ew. nadać mu ID i rozpoznawac go po identyfikatorze, tak jak jest to w bazach danych), już kompletnie nie pomyślałeś tylko piszesz zmienne luzem playerA_choice, playerB_wins etc. Czyli koncepcja Gracz w ogóle nie istnieje w twoim programie. Robisz grę bez graczy, jedynie z "wyborami graczy" czy z "wygranymi graczy".)

Oczywiście z abstrakcjami też można przesadzić. Jakiś programista Javy do tego co robisz pewnie porobiłby 15 różnych klas, implementując 30 różnych interfejsów i 10 różnych wzorców projektowych - co byłoby mocno przekombinowane ;)


((0b10*0b11*(0b10**0b101-0b10)**0b10+0b110)**0b10+(100-1)**0b10+0x10-1).toString(0b10**0b101+0b100);
edytowany 6x, ostatnio: LukeJL, 2015-10-28 16:31
twój kod jest bardzo imperatywny no to akurat nic złego, chyba szukałeś innego słowa :D - Wizzie 2015-10-28 17:29
Kluczem jest słowo "bardzo" ;) Ale w sumie faktycznie to o co mi chodzi można wyrazić raczej zdaniem, że cała logika jest wpisana na sztywno i że co prawda są pewne abstrakcje (tabela tranzycji), to jednak poza tym kod gry nie daje się w żaden sposób sparametryzować (np. nie da się dodać 3 gracza, bo fakt, że graczy jest tylko 2 jest wpisany na sztywno w logikę gry). - LukeJL 2015-10-28 18:22
btw. ta tabela tranzycji, która tam wisi też dobra nie jest, bo też ma wpisane na sztywno liczbę graczy. Ale autor tematu i ta napisał, że to "Pozostałość po starym koncepcie. " więc zapewne w jego przypadku i implementacji to nie wyszło, mimo że taka tabela tranzycji gdzie indziej mogłaby być dobra... - LukeJL 2015-10-28 18:25
(chociaz w sumie... jakby przelecieć przez każdą parę graczy, to nawet by można było ją zastosować). - LukeJL 2015-10-28 18:26

Pozostało 580 znaków

2015-10-31 21:36
0

Powołując się na python zen:

Simple is better than complex

Myślę, że tutaj trafiono w samo sedno. Kod jest nadal prosty i zrozumiały. Co prawda można sugerować Ci sztuczki z pythona bądź podział na funkcje, klasy czy też inne praktyki (testy, wzorce), ale przy tak prostych zadaniach to nie jest konieczne. W każdym razie jeśli na tym etapie zaczniesz przejmować się samą formą niż treścią to w niedługim czasie zobaczymy tutaj Twoje metaprogramowanie :-)

edytowany 1x, ostatnio: pyholic, 2015-10-31 21:45
nie uważasz, że czytelny kod jest prostszy od nieczytelnego? ;) - Wizzie 2015-11-01 08:38
Odpowiedź zawierasz w pytaniu. Ja natomiast chciałem podkreślić, że kod prosty również może być czytelny. - pyholic 2015-11-01 09:26

Pozostało 580 znaków

2015-11-07 23:29
0

Hej, dzięki za liczne odpowiedzi ;) Można na was liczyć. Spróbuje się odnieść do niektórych zarzutów, zaprezentuję nowy kod i przedstawię listę pytań.
@Wizzie: przyznam, że pierwszego i ostatniego akapitu twego postu po prostu nie zrozumiałem. Ale też nie poświecałem zbytnio czasu na to. Po prostu nie miałem kiedy. Ale dzięki, szczególnie za to o zasadności stosowania funkcji

@LukeJL: bardzo fajnie i zwięźle wypunktowałeś co jest źle. Dzięki.

Wrzucam nowy kod. Troszkę go rozbudowałem o dodatkowe funkcje (dodawanie graczy, zarządzanie dodanymi już graczmi, generowanie imion graczy według potrzeby, kamień, papier, nożyce, jaszczurka i Spock :), rundy).

import random
import time
import getpass

players_list = []

def generate_player_name():
    names = ['Plaska Dziewica', 'Zbutwialy Piernik', 'Mistrz Wegorza', 'Zjadacz Sedesow',
             'Stanikowy Deszcz', 'Smetny Pierd', 'Sprzedam Seata', 'Zimna Warka',
             'Jacek Maly Wacek', 'Waleczny Mlot', 'Szalony Ziemniak', 'Sheldon'
             'Waz Rzeczny', 'Tururu Tururu', 'Jest Niebezpieczny' ]

    decision = ' '
    possible_decision = ('Y', 'N')
    while decision not in possible_decision:
        player_name = random.choice(names)
        decision = input('>> Do The Name ' + player_name + " Is OK With You? If Not I Will Draw Again [Y/N] ").upper()

        if(decision == 'Y'):
            print('>> Great then!', player_name)
            return player_name
        elif decision == 'N':
            decision = ' '

def create_player(decision, possible_decisions):
    flag = ' '
    possible_flags = {'C': 'is_computer', 'H': 'is_human'}
    while(flag not in possible_flags):
        flag = input('>> Will The Player Be Controlled By [H]uman or [C]omputer? ').upper()

    if(decision == 'M'):
        player_name = input('>> Type The Name:')  
    elif(decision == 'A'):
        player_name = generate_player_name()

    players_list.append( {'player_name': player_name,
                         'player_flag': possible_flags[flag],
                         'player_decision': None,
                         'player_points': 0}
                        )

def add_player():
    list_status = len(players_list)
    decision = ' '

    while decision != 'B':
        decision = input(">> Do You Want To Create New Player [M]anualy Or Should I Do It [A]utomaticly (I'll Generate The Name)?\n   [B]ack To Main Menu ").upper()

        possible_decisions = ['A', 'M']
        if(decision in possible_decisions):
            create_player(decision, possible_decisions)

            decision = ' '
            possible_decisions = ['Y', 'N']
            while decision not in possible_decisions:
                decision = input('>> You Just Added The Player! Do You Want To Add Another One? [Y/N] ' ).upper()

                if(decision == 'N'):
                    decision = 'B'
                    break

        if(decision == 'B'):
            print('>> You Just Added:',  len(players_list) - list_status, 'Players')

def play():
    print(">> We Will Play In That Order:", end = ': ')
    for player in players_list:
        print(player['player_name'], end = ', ')
    print() # newline

    number = 99
    while not number <= 5 or number <= 0:
        number = int(input('>> Before You Start Type How Many Rounds Do You Want To Play?\n   The Maximum Number Of Rounds Is Five '))

        if number > 5:
            print('As I Said You Cannot Play More Rounds Than Five')
        elif number == 0:
            print('In This Case I Predict The Score. NOBODY WON AND NOBODY LOST')
        elif number < 0:
            print("I Won't Comment On That. Just Type Once Again")

        for rounds in range(0, number):
            print('\n>> Round', rounds + 1)
            make_choice()
            give_points()

    decide_winner()
    clean_points()

def make_choice():
    options = {1: 'rock', 2: 'paper', 3: 'scissors', 4: 'lizard', 5: 'Spock'}

    for player in players_list:
        if(player['player_flag'] == 'is_computer'):
            print('>> It Is {player_name} Turn! The Player Is Controled By The Computer'.format(player_name = player['player_name']))
            for i in range(1, 4):
                print('>> {i}... '.format(i = i))
                time.sleep(1)

            player_decision = random.randint(1, 5)

        elif(player['player_flag'] == 'is_human'):
            player_decision = 2
            while player_decision < 1 and player_decision > 5: 
                player_decision = int(getpass.getpass(">> It Is {player_name} Turn! The possible choices:\n   1: 'rock', 2: 'paper', 3: 'scissors', 4: 'lizard', 5: 'Spock' ".format(player_name = player['player_name'])))

        print('>> {player_name} Made a Choice!\n'.format(player_name = player['player_name']));    
        player['player_decision'] = options[player_decision]

def give_points():
    results = {('rock', 'rock'): 'game_is_draw',
               ('rock', 'paper'): 'playerB_wins',
               ('rock', 'scissors'): 'playerA_wins',
               ('rock', 'lizard'): 'playerA_wins',
               ('rock', 'Spock'): 'playerB_wins',
               ('paper', 'rock'): 'playerA_wins',
               ('paper', 'paper'): 'game_is_draw',
               ('paper', 'scissors'): 'playerB_wins',
               ('paper', 'lizard'): 'playerB_wins',
               ('paper', 'Spock'): 'playerA_wins',
               ('scissors', 'rock'): 'playerB_wins',
               ('scissors', 'paper'): 'playerA_wins',
               ('scissors', 'scissors'): 'game_is_draw',
               ('scissors', 'lizard'): 'playerA_wins',     
               ('scissors', 'Spock'): 'playerB_wins',
               ('lizard', 'rock'): 'playerB_wins',
               ('lizard', 'paper'): 'playerA_wins',
               ('lizard', 'scissors'): 'playerB_wins',
               ('lizard', 'lizard'): 'game_is_draw',
               ('lizard', 'Spock'): 'playerA_wins',
               ('Spock', 'rock'): 'playerA_wins',
               ('Spock', 'paper'): 'playerB_wins',
               ('Spock', 'scissors'): 'playerA_wins',
               ('Spock', 'lizard'): 'playerB_wins',
               ('Spock', 'Spock'): 'game_is_draw'
              }

    print('Results:')
    i = 1
    for playerA in players_list:
        for playerB in players_list[i:]:
            result = results[playerA['player_decision'], playerB['player_decision']]

            if result == 'game_is_draw':
                playerA['player_points'] += 0.5
                playerB['player_points'] += 0.5
                print('  - Players {playerA_name} And {playerB_name} Has Drawn. Each Of Them Got 0.5 Point'
                      .format(playerA_name = playerA['player_name'], playerB_name = playerB['player_name']))

            elif result == 'playerA_wins':
                playerA['player_points'] += 1
                print('  - Player {playerA_name} Won With {playerB_name}. Players {playerA_name} Got 1 Point'
                      .format(playerA_name = playerA['player_name'], playerB_name = playerB['player_name']))

            elif result == 'playerB_wins':
                playerB['player_points'] += 1
                print('  - Player {playerB_name} Won With {playerA_name}. Players {playerB_name} Got 1 Point'
                      .format(playerA_name = playerA['player_name'], playerB_name = playerB['player_name']))

        i += 1

def decide_winner():
    sorted_list = sorted(players_list, key=lambda k: k['player_points'], reverse=True)

    i = 0
    while sorted_list[i]['player_points'] == sorted_list[i + 1]['player_points']:
        i += 1

    print('\n>> The Winner Is...', end = ' ')
    time.sleep(2)
    if i == 0:
        print(sorted_list[0]['player_name'].upper(), '!!!')
    elif i > 0:
        print('There Is a Draw Between ', end = '')
        for j in range (0, i + 1):
            print(sorted_list[j]['player_name'], end = ', ')

        print() #newline

    print('>> Congratulations! You Have Got', sorted_list[0]['player_points'], 'Points')

    print('>> Results:')
    for player in sorted_list:
        print('  ', player['player_name'], player['player_points'])

    print() #newline

def managment_players():
    print('>> The List Of Players: ')
    for player in players_list:
        print('   - {player_name} is controled by {player_flag}'. format(player_name = player['player_name'], player_flag = player['player_flag'][3:]))

    possible_decision = ('D', 'B')
    decision = ' '
    while decision not in possible_decision:
        decision = input('>> Do You Want To [D]elete a Player? [B]ack To Main Menu ').upper()

        if decision == 'D':
            number = 99
            while not number < len(players_list) + 1:
                number = int(input(">> What Player Do You Want To Delete? Give Me a Number "))

                if number > len(players_list) + 1:
                    print('>> The Player With {number} Number Does Not Exist'.format(number = number)) 

                else:
                    possible_decision = ('Y', 'N')
                    while decision not in possible_decision:
                        decision = input('>> Are You Sure You Want To Delete {player_name} Player? [Y/N] '.format(player_name = players_list[number - 1]['player_name'])).upper()

                        if decision == 'Y':
                            del players_list[number - 1]
                            print('>> You Just Removed The Player!')
                            break

                    possible_decision = ('D', 'B')

def clean_points():
    for player in players_list:
        player['player_points'] = 0

    sorted_list = []                       

''' for tests
players_list.append( {'player_name': 'Marek',
                        'player_flag': 'is_human',
                        'player_decision': None,
                        'player_points': 0}
                    )

players_list.append( {'player_name': 'Karolinka',
                        'player_flag': 'is_computer',
                        'player_decision': None,
                        'player_points': 0}
                    )

players_list.append( {'player_name': 'Sraromir',
                        'player_flag': 'is_computer',
                        'player_decision': None,
                        'player_points': 0}
                    )

players_list.append( {'player_name': 'Smutna Julka',
                        'player_flag': 'is_computer',
                        'player_decision': None,
                        'player_points': 0}
                    )
'''

print(">> Welcome To Rock-Paper-Scissors-Lizard-Spock Game. All Rights Reserved. Enjoy! ")
decision = input('>> Before You [P]lay, Remeber To [A]dd Players. You Can [M]anage The List Of Participants At Any Time.\n   When You Get Tired Of The Game, Just [E]xit ').upper()

while(decision != 'E'):
    if(decision == 'E'):
       print('>> Have a Nice Day! ')

    elif(decision == 'P'):
        if not players_list:
            print('>> At First You Need To Add Players. Do It And I Will Let You Play')
        else:
            play()

    elif(decision == 'A'):
        add_player()

    elif(decision == 'M'):
       if not players_list:
            print(">> You Moron! You Didn't Add Any Players Yet!")
       else:
            managment_players()

    decision = input('>> So What Do You Want To Do Now? [P]lay, [A]dd a New Player, [M]anage Already Added Players, Or Just [E]xit? ').upper()

A teraz pytania ode mnie dla was:

  1. Jak powinien wyglądać główny blok kodu? Jaka jest konwencja? Czy powinienem go zamknąć w main() i po prostu go wywołać czy tak jak zrobiłem też jess OK?
  2. Jak wygląda dobrze napisany odpowiednik Switch: case w pythonie za pomocą if'ów?
  3. Czy jest jakiś lepszy sposób na wymuszeniu na użytkowniku odpowiedniego znaku przy wybiorze niż zastosowane przeze mnie:
    possible_decision = ['option1', 'option2']
    decision = ' '
    while decision not in possible_decision:
       decision = input()
  4. Jak brzmią dobrze nazwane funkcje? :)
  5. Czy nie robię bardzo źle że używam zmiennej globalnej (players_list = [])?
  6. Co dostrzegacie gdzieś powtarzającą się logikę o której wspomniał @LukeJL?
edytowany 2x, ostatnio: jaSwiezak, 2015-11-07 23:33
teraz kod jest tak długi, że aż nie chce się go przeglądać ;) Dla nadawania nieokreśłonej wartości zamiast tekstu ze spacja np. flag = ' ', decision = ' ' można użyć None lub False czyli flag = None, decision = None. Wydaje mi się to bardziej czytelne. - furas 2015-11-08 00:51
@furas: zanotowane, dzięki. - jaSwiezak 2015-11-09 17:30

Pozostało 580 znaków

2015-11-08 14:04
2
jaSwiezak napisał(a):

@Wizzie: przyznam, że pierwszego i ostatniego akapitu twego postu po prostu nie zrozumiałem

  1. Jak powinien wyglądać główny blok kodu? Jaka jest konwencja? Czy powinienem go zamknąć w main() i po prostu go wywołać czy tak jak zrobiłem też jess OK?

Tego właśnie dotyczył mój pierwszy akapit. W Pythonie, w momencie gdy ktoś chce zaimportować twoją bibliotekę, cały kod w niej jest po prostu wykonywany. Na przykład weźmy taki kod w pliku o nazwie super_obliczenia.py:

def area_of_rectangle(a, b):
    return a * b

area = area_of_rectangle(5, 10)
test = area == 50
print(area)
print(test)

Czyli jakaś prosta funkcja do liczenia pola prostokąta i 4 linijki prymitywnego testu. Pokazałeś ten kod swojemu szwagrowi Markowi. Marek stwierdził: ta funkcja do liczenia pola jest zajebista! Zaimportuje on sobie tą ją w taki sposób:

from super_obliczenia import area_of_rectangle

Funkcja ładnie się zaimportowała, wszystko działa jak należy, Marek się cieszy. Ale nagle patrzy do konsoli, a tu dwie linijki jakiegoś tekstu. Markowi to bardzo nie pasuje, bo to może wprowadzić w zakłopotanie użytkowników jego programu. W rezultacie tego Marek popada w depresję, sięga do butelki i stacza się na niziny społeczne. W jaki sposób możemy podać rękę Markowi i wyciągnąć go z tej trudnej sytuacji?

A no okazuje się, że można w bardzo prosty sposób. Jeśli uruchamiasz swój program za pomocą komendy python super_obliczenia.py to wszystko działa jak należy, tak? Problem pojawia się, jeśli ktoś importuje twój program z innego modułu. Rozwiązanie to rozgraniczenie tych dwóch rzeczy. Robimy to wykorzystując magiczną zmienną __name__, znajdującą się w każdym module jaki napiszemy. Jeśli uruchamiamy nasz program bezpośrednio (z konsoli), to zmienna __name__ będzie miała wartość __main__. Więc przerabiamy nasz kod w taki sposób:

def area_of_rectangle(a, b):
    return a * b

if __name__ == '__main__':
    area = area_of_rectangle(5, 10)
    test = area == 50
    print(area)
    print(test)

W tym momencie Marek zapisuje się do AA, powoli wychodzi z dołka i wszystko wraca do normy, a nawet jest lepiej, bo Marek jest bogatszy o naszą wspaniałą funkcję. A nasz program działa identycznie jak wcześniej.


Czy powinienem go zamknąć w main()

W twoim przypadku tak, bo jest go dużo. W powyższym przypadku niekoniecznie, bo to tylko 4 linijki.

Pozostało 580 znaków

2015-11-09 17:29
0

@Wizzle: okej, już wiem o co chodzi. Rozumiem, że dodanie warunku

if __name__ == '__main__':

jest po prostu dobrym nawykiem, tak? Korzystając z okazji: polecacie jakąś dobrą stronkę z dobrze napisanymi kodami w pythonie? Oczywiście na poziomie laika.

Dzięki za zobrazowanie mi tego ;) doceniam.

edytowany 1x, ostatnio: jaSwiezak, 2015-11-09 17:29
można uznać za dobry nawyk, ale to raczej konieczność dla kodu, który może być uruchomiony z konsoli - Wizzie 2015-11-09 18:02

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0