Наследование

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

Суть наследования здесь схожа с наследованием объектами от классов. Дочерние классы наследуют атрибуты родительских, а также могут переопредять атрибуты и добавлять свои.

Простое наследование методов родительского класса

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

Связь между родительским и дочерним классом устанавливается через дочерний: родительские классы перечисляются в скобках после его имени.

class Table:
    def __init__(self, l, w, h):
        self.lenght = l
        self.width = w
        self.height = h
 
class KitchenTable(Table):
    def setPlaces(self, p):
        self.places = p
 
class DeskTable(Table):
    def square(self):
        return self.width * self.length

В данном случае классы KitchenTable и DeskTable не имеют своих собственных конструкторов, поэтому наследуют его от родительского класса. При создании экземпляров этих столов, передавать аргументы для __init__() обязательно, иначе возникнет ошибка:

>>> from test import *
>>> t1 = KitchenTable()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 3 required positional arguments: 'l', 'w', and 'h'
>>> t1 = KitchenTable(2, 2, 0.7)
>>> t2 = DeskTable(1.5, 0.8, 0.75)
>>> t3 = KitchenTable(1, 1.2, 0.8)

Несомненно можно создавать столы и от родительского класса Table. Однако он не будет, согласно неким родственным связям, иметь доступ к методам setPlaces() и square(). Точно также как объект класса KitchenTable не имеет доступа к единоличным атрибутам сестринского класса DeskTable.

>>> t4 = Table(1, 1, 0.5)
>>> t2.square()
1.2000000000000002
>>> t4.square()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Table' object has no attribute 'square'
>>> t3.square()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'KitchenTable' object has no attribute 'square'

В этом смысле терминология "родительский и дочерний класс" не совсем верна. Наследование в ООП – это скорее аналог систематизации и классификации наподобие той, что есть в живой природе. Все млекопитающие имеют четырехкамерное сердце, но только носороги – рог.

Полное переопределение метода надкласса

Что если в подклассе нам не подходит код метода его надкласса. Допустим, мы вводим еще один класс столов, который является дочерним по отношению к DeskTable. Пусть это будут компьютерные столы, при вычислении рабочей поверхности которых надо отнимать заданную величину. Имеет смысл внести в этот новый подкласс его собственный метод square():

class ComputerTable(DeskTable):
    def square(self, e):
        return self.width * self.length - e

При создании объекта типа ComputerTable по-прежнему требуется указывать параметры, так как интерпретатор в поисках конструктора пойдет по дереву наследования сначала в родителя, а потом в прародителя и найдет там метод __init__().

Однако когда будет вызываться метод square(), то поскольку он будет обнаружен в самом ComputerTable, то метод square() из DeskTable останется невидимым, т. е. для объектов класса ComputerTable он окажется переопределенным.

>>> from test import ComputerTable
>>> ct = ComputerTable(2, 1, 1)
>>> ct.square(0.3)
1.7

Дополнение, оно же расширение, метода

Если посмотреть на вычисление площади, то часть кода надкласса дублируется в подклассе. Этого можно избежать, если вызвать родительский метод, а потом дополнить его:

class ComputerTable(DeskTable):
    def square(self, e):
        return DeskTable.square(self) - e 

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

Рассмотрим другой пример. Допустим, в классе KitchenTable нам не нужен метод, поле places должно устанавливаться при создании объекта в конструкторе. В классе можно создать собсвенный конструктор с чистого листа, чем переопределить родительский:

class KitchenTable(Table):
    def __init__(self, l, w, h, p):
        self.length = l
        self.width = w
        self.height = h
        self.places = p

Однако это не лучший способ, если дублируется почти весь конструктор надкласса. Проще вызвать родительский конструктор, после чего дополнить своим кодом:

class KitchenTable(Table):
    def __init__(self, l, w, h, p):
        Table.__init__(self, l, w, h)
        self.places = p

Теперь при создании объекта типа KitchenTable надо указывать в конструкторе четыре аргумента. Три из них будут переданы выше по лестнице наследования, а четвертый оприходован на месте.

>>> tk = KitchenTable(2, 1.5, 0.7, 10)
>>> tk.places
10
>>> tk.width 
1.5

Практическая работа

Разработайте программу по следующему описанию.

В некой игре-стратегии есть солдаты и герои. У всех есть свойство, содержащее уникальный номер объекта, и свойство, в котором хранится принадлежность команде. У солдат есть метод "иду за героем", который в качестве аргумента принимает объект типа "герой". У героев есть метод увеличения собственного уровня.

В основной ветке программы создается по одному герою для каждой команды. В цикле генерируются объекты-солдаты. Их принадлежность команде определяется случайно. Солдаты разных команд добавляются в разные списки.

Измеряется длина списков солдат противоборствующих команд и выводится на экран. У героя, принадлежащего команде с более длинным списком, поднимается уровень.

Отправьте одного из солдат первого героя следовать за ним. Выведите на экран идентификационные номера этих двух юнитов.

Курс с примерами решений практических работ и всеми уроками: android-приложение, pdf-версия.

Комментарии

class Solder:
	def __init__(self, number, team):
		self.team = team
		self.number = number
 
	def to_hero(self, hero):
		return hero.number, self.number
 
class Hero:
	def __init__(self, number, team_number, team): # Если сдесь обьявить team=[] то почему то у нас список не сбрасывается для каждого отдельного экземпляра.
		self.team_number = team_number
		self.number = number
		self.lvl = 0
		self.team = team
 
	def up_lvl(self):
		self.lvl += 1
 
	def add_solder(self, solder):
		return self.team.append(solder)
 
	def look_count_team(self):
		return len(self.team)
 
hero_team_first = Hero(1, 1, [])
hero_team_second = Hero(2, 2, [])
count = 0
while count < 10:
	team_for_solder = random.randrange(1, 3)
	number_for_solder = random.random()
	if team_for_solder == 1:
		hero_team_first.add_solder(Solder(number_for_solder, team_for_solder))
	else:
		hero_team_second.add_solder(Solder(number_for_solder, team_for_solder))
	count += 1	
 
 
 
if hero_team_first.look_count_team() > hero_team_second.look_count_team():
	hero_team_first.up_lvl()
else:
	hero_team_second.up_lvl()
 
print(hero_team_first.team[0].to_hero(hero_team_first))

Первый вопрос следует из комментария, почему если мы объявим список как аргумент по умолчанию, то он становиться единым для все экземпляров класса.

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

Ответ на от Iliner

class Hero:
    def __init__(self, number, team_number, team=[]):
        self.team_number = team_number
        self.number = number
        self.lvl = 0
        self.team = team
 
first = Hero(1, 1)
second = Hero(2, 2)
first.team.append('ben')
second.team.append('ken')
print(first.team, second.team)
print(first.team is second.team)

Результат:

['ben', 'ken'] ['ben', 'ken']
True

Переменные first.team и second.team ссылаются на один и тот же объект. Спецэффект связан с особенностями Питона при работе с изменяемыми типами данных. Список к таковым относится. Суть: при связывании списка с новой переменной, он не копируется, а на один и тот же список начинают указывать множество переменных.

Когда аргумент не передается в метод, а используется список [] по-умолчанию, то получается, что он создается единожды. Ссылка на него присваивается переменной team. Далее ссылка на этот же список присваивается переменной self.team. Когда создается новый объект, то новая локальная переменная team связывается с уже существующим списком, который уже не пуст.

Второй вопрос. Если ходите избавиться от аргумента hero, то надо в каком-то поле сохранить героя команды например в методе __init__. Получится длиннее, чем с аргументом hero в методе to_hero.

Уникальный идентификатор объектов (number) реализован не совсем верно. Тема про наследование. По-идее общие атрибуты выносятся в общий надкласс.

Ответ на от plustilino

import random
 
class Character:
    uniq_number = 0
    def __init__(self, number_team):
        self.uniq_number = number_team
        Character.uniq_number += 1
        self.uniq_number = Character.uniq_number
 
class Hero(Character):
    def __init__(self, number_tean):
        super(Hero, self).__init__(number_tean)
        self.lvl = 0
        self.team_list = []
 
    def up_lvl(self):
        self.lvl += 1
 
    def add_solder(self, unit):
        self.team_list.append(unit)
 
    def len_team(self):
        return len(self.team_list)
 
class Solder(Character):
 
    def to_hero(self, hero):
        return "Уникальный номер солдата: {}. Уникальный номер Героя: {} ".format(self.uniq_number, hero.uniq_number)
 
first_hero = Hero(1)
second_hero = Hero(2)
count = 1
while count < 10:
    number_team = random.randrange(1, 3)
    if number_team == 1:
        first_hero.add_solder(Solder(number_team))
    else:
        second_hero.add_solder(Solder(number_team))
    count += 1
 
print(first_hero.len_team(), second_hero.len_team())
if first_hero.len_team() > second_hero.len_team():
    first_hero.up_lvl()
else:
    second_hero.up_lvl()
print(first_hero.team_list[0].to_hero(first_hero))

Только не кидайтесь помидорами)) случился такой затык
import random
class unit:
    def __init__(self, team = random.randint(1, 2)):
        self.numb = id(self)
        self.team = team
 
class soldier(unit):
    def go_with_hero(hero):
        pass
class hero(unit):
    def level_up():
        pass
 
Super = hero(1)
Puper = hero(2)
Super_team = []
Puper_team = []
for i in range(int(input("Введите количество солдат: ")):
    i = soldier()
    if i.team == 1:
        Super_team.append(i)
    else:
        Puper_team.append(i)
при проверке длины списков всем солдатам присвоен один и тот же номер команды, либо 1 либо 2.

Вопрос почему не рандомно каждому солдату?

Ответ на от Илья

Видимо выражение random.randint(1, 2) при использовании его в качестве аргумента метода вычисляется единожды, когда интерпретатор первый раз читает класс. Это происходит до вызова класса. Потом когда создаются объекты используется вычисленное значение. Т. е. на момент вызова имеем например def __init__(self, team=1). Когда создаются герои, то значение тим заменяется на переданное. Когда ничего не передается (в случае солдат), то берется по умолчанию, т. е. то которое было вычислено на момент "компиляции" класса.

Ответ на от plustilino

Спасибо за версию. На след день немного переосмыслил код и всё получилось:
import random
import time
class unit:
    def __init__(self):
        self.numb = id(self)
        self.team = random.randint(1,2)
 
class soldier(unit):
    def go_with_hero(hero):
        pass
class hero(unit):
    def __init__(self, team):
        self.team = team
    def level_up():
        pass
 
Super = hero(1)
Puper = hero(2)
Super_team = []
Puper_team = []
for i in range(int(input("Введите количество солдат: "))):
    i = soldier()
    if i.team == 1:
        Super_team.append(i)
    else:
        Puper_team.append(i)
Вывод - во всех непонятных случаях - ложитесь спать)))

Утро вечера мудренее))

Ответ на от Илья

Мой Вариант)))
import random
class unit:
    def __init__(self):
        self.numb = id(self)
        self.team = random.randint(1,2)
 
class soldier(unit):
    def go_with_hero(self, hero = 0):
        return(id(hero), id(self))
class hero(unit):
    lvl = 0
    def __init__(self, team):
        unit.__init__(self)
        self.team = team
    def level_up(self):
        self.lvl += 1
Super = hero(1)
Puper = hero(2)
Super_team = []
Puper_team = []
for i in range(int(input("Введите количество солдат: "))):
    i = soldier()
    if i.team == 1:
        Super_team.append(i)
    else:
        Puper_team.append(i)
if len(Super_team) > len(Puper_team):
    Super.level_up()
elif len(Super_team) < len(Puper_team):
    Puper.level_up()
else:
    print("Герои имеют равные силы!!")
legend_team = Super_team[0].go_with_hero(Super)
print("Уровен героя Super - {}\nУровен героя Puper - {}".format(Super.lvl, Puper.lvl))
print("Два великих воина - {} и {} отправилис навстречу подвигам!!!".format(Super_team[0].go_with_hero(Super)[0],Super_team[0].go_with_hero(Super)[1]))   

import random
 
class unit:
    def __init__(self, id, team):
        self.id = id
        self.team = team
 
class soldier(unit):
    def follow(self, hero):
        print "Soldier with ID {} is following Hero with ID {}".format(self.id, hero.id)
 
class hero(unit):
    def __init__(self, id, team):
        unit.__init__(self, id, team)
        self.level = 0
 
    def levelup(self, team_size):
        self.level = team_size / 10
 
teams = ['good_team', 'bad_team']
gandalf = hero(1, teams[0])
sauron = hero(2, teams[1])
 
soldiers = []
good_team = [gandalf]
bad_team = [sauron]
 
for i in range(1,1000):
    soldiers.append(soldier(i, random.choice(teams)))
 
for warrior in soldiers:
    if warrior.team == 'good_team':
        good_team.append(warrior)
    else:
        bad_team.append(warrior)
 
print "Good team size: {}, Bad team size: {}".format(len(good_team), len(bad_team))
 
gandalf.levelup(len(good_team))
sauron.levelup(len(bad_team))
 
print "Gandalf lvl {}, Sauron lvl {}".format(gandalf.level, sauron.level)
 
random.choice(good_team).follow(gandalf)

Ответ на от Михаил

Отлично! Хорошим тоном программирования Python считается называть классы с большой буквы. Если не трудно,поправьте пожалуйста

import random
class unit: #создаем родительский клас юнитов с атрибутами: номер и команда
    def __init__(self, n,team):
        self.n=n
        self.team=team
class heroes(unit): # создаем клас героев и добавляем атрибут уровень
    def __init__(self,name,n,team,level=0):
        self.name=name
        self.level = level
        self.team=team
    def level_up(self, incr): # создаем метод повышения уровня, который принимает аргумент "на сколько повышен уровень"
        self.level+=incr
 
class soldier(unit): # создаем клас солдата с методом следовать за героем
    def follow_heroes(self,heroes):
        print("\n"+"Для охраны своих владений герой {} выбрал опытного воина № {} и отправился с ним в поход.".format(heroes.name, self.n))
Tristan,Merlin=heroes("Tristan",1,"red"),heroes("Merlin",2,"green") # создаем два объекта героя
red_team=[] #создаем
green_team=[] #две коменды
quantity=int(input("Количество воинов:"))+1 # пользовательский ввод обозначает общее количество воинов
for i in range(1,quantity): #создам воинов и распределяем между командами героев
    t=random.randint(0,1)
    i=soldier(i,t)
    if i.team==0:
        red_team.append(i)
        i.team="red"
    else:
        green_team.append(i)
        i.team="green"
if len(red_team)>len(green_team): # определяем уровень героя в зависимости от того у кого больше солдат
    Tristan.level_up(1)
elif len(red_team)<len(green_team):
    Merlin.level_up(1)
if len(red_team) >= 10:
    Tristan.level_up(len(red_team) // 5)
if len(green_team)>=10:
    Merlin.level_up(len(green_team)//5)
 
# выводим на экран списки команд
print("В войске героя по имени",Tristan.name+",",str(Tristan.level)+"-го уровня,",len(red_team),"знатных воинов!")
for i in red_team:
    print(i.n, i.team, end=", ")
print("\n"+"В войске героя по имени",Merlin.name+",",str(Merlin.level)+"-го уровня,",len(green_team),"знатных воинов!")
for i in green_team:
    print(i.n,i.team, end=", ")
#выводим случайное имя героя и номер одного из солдат
who=random.randint(0,1)
if who==1:
    t=red_team
    h=Tristan
else:
    t=green_team
    h=Merlin
random.choice(t).follow_heroes(h)

import random
 
class Person:
    def __init__(self, team_id):
        self.id = id(self)
        self.team_id = team_id
    #def __del__(self):
    #    print(f"Я ({self.id}) из команды {self.team_id} покидаю Вас, до свидания.")
 
class Hero(Person):
    level = 0
    def level_up(self, delta = 0):
        if delta:
            self.level += delta
        else:
            self.level += 1
        print(f"Я герой ({self.id}) из команды {self.team_id}, мой уровень = {self.level}")
 
class Solder(Person):
    number = -1
    def set_number(self, number):
        self.number = number
    def to_hero(self, hero):
        self.hero = hero
    def folow_to_hero(self):
        try:
            print(f"Я {self.number} солдат ({self.id}) из команды {self.team_id} следую за героем ({self.hero.id}).")
        except AttributeError:
            print(f"Я {self.number} солдат ({self.id}) из команды {self.team_id} не имею героя.")
 
teams = []
 
teams_cnt = 2
for i in range(teams_cnt):
    teams.append([[], Hero(i+1)])
 
solder_cnt = 100
for i in range(solder_cnt):
    t = random.randint(1,teams_cnt)
    s = Solder(t)
    s.to_hero(teams[t-1][1])
    s.set_number(len(teams[t-1][0])+1)
    teams[t-1][0].append(s)
 
teams_sol_cnt = []
for i in range(teams_cnt):
    print(f"В команде {i+1}: {len(teams[i][0])} солдат(а)")
    teams_sol_cnt.append(len(teams[i][0]))
 
team_max = max(teams_sol_cnt)
for i in range(len(teams_sol_cnt)):
    if team_max == teams_sol_cnt[i]:
        teams[i][1].level_up()
 
rnd_t = random.randint(1,teams_cnt)-1
teams[rnd_t][0][random.randint(1,teams_sol_cnt[rnd_t])-1].folow_to_hero()
 
teams.clear()

import itertools
import random
 
class Unit:
  new_id = itertools.count()
  def __init__(self, command):
    self.id = next(self.new_id)
    self.command = command
 
class Soldier(Unit):
  def __init__(self, command):
    Unit.__init__(self, command)
 
  def move_to_hero(self, Hero):
    print('Moving for hero -', Hero.name, sep=' ')
 
 
class Hero(Unit):
  def __init__(self, command, name):
    Unit.__init__(self, command)
    self.name = name
    self.level = 1
 
  def level_up(self):
    self.level += 1
    print(self.name,', level up!')
 
commands = ['British', 'Norway']
 
h1 = Hero(commands[0], 'Olaf')
h2 = Hero(commands[1], 'Henrich')
 
british_army = []
norway_army = []
 
 
print(range(random.randint(14, 16), random.randint(30, 32)))
 
for x in range(random.randint(14, 16), random.randint(30, 32)):
  random_nations = random.choice(commands)
  if random_nations == 'British':
    british_army.append(Soldier(random_nations))
  else: 
    norway_army.append(Soldier(random_nations))
 
print('British - ',len(british_army))
 
print('Norway - ',len(norway_army))
 
if len(british_army) > len(norway_army):
  h2.level_up()
else:
  h1.level_up()
 
random_soldier = random.choice(british_army)
 
random_soldier.move_to_hero(h1)

from random import choice
 
class Unit:
    new_id = 0
    def __init__(self):
        self.id = Unit.new_id
        Unit.new_id += 1
 
 
class Soldier(Unit):
    def __init__(self):
        Unit.__init__(self)
    def move_to_hero(self, hero):
        print('Moving for hero -', hero.id)
 
 
class Hero(Unit):
    def __init__(self):
        Unit.__init__(self)
        self.level = 1
    def level_up(self):
        self.level += 1
        print(f'Level up!\nYour lvl: {self.level}')
 
COUNT_SOLDIER = 10
 
class Command:
    def __init__(self, name, hero):
        self.name = name
        self.hero = hero
        self.soldiers = []
    def add_soldier(self, soldier):
        self.soldiers.append(soldier)
    @property
    def count_soldier(self):
        return len(self.soldiers)
 
def loop(command_names):
    commands = []
    for name in command_names:
        new_team = Command(name, Hero())
        commands.append(new_team)
 
    i = 0
    while i < COUNT_SOLDIER:
        choice(commands).add_soldier(Soldier())
        i += 1
 
    for command in commands:
        count_soldier = command.count_soldier
        if count_soldier == 0:
            count_soldier = 'no soldiers'
        elif count_soldier < 2:
            count_soldier = str(count_soldier) + ' soldier'
        else:
            count_soldier = str(count_soldier) + ' soldiers'
 
        print(f'In command {command.name}: {count_soldier}')
 
    command_win = commands[0]
 
    for command in commands[1:]:
        count_soldiers = command.count_soldier
        if count_soldiers > command_win.count_soldier:
            command_win = command
 
    command_win.hero.level_up()
 
    if commands[0].count_soldier:
        hero_1 = commands[0].hero
        soldier_1 = commands[0].soldiers[0]
        soldier_1.move_to_hero(hero_1)
        print(f'Hero id: {hero_1.id}. Soldier id: {soldier_1.id}')
 
 
loop(['red', 'blue', 'green'])

import random
class war:
    def __init__(self, i, a):
        self.id = i
        self.army = a
 
 
class solder(war):
    def __init__(self, i, a):
        war.__init__(self, i, a)
 
    def myindex(self, nil):
        self.index = nil
 
    def randunit(self, rnd):
        self.runit = rnd
 
    def follow(self, hero):
        self.myhero = hero
        print (f'я солдат этой дивизии под номером {self.index}, мой id:{self.runit} иду за капитаном id: {self.myhero}') 
 
 
class hero(war):
    def __init__(self, i, a):
        war.__init__(self, i, a)
    def up(self, level=50):
        print (f'а я командор id: {self.id}, мой уровень {level+50}!')
 
air = []
land = []
sea = []
 
#механизм уникального числа)
num = list(range(507))
i = 0
for e in num:
    num[i] = random.random()
    num[i] = str(num[e])
    i+=1
 
idx = 0
for st in num:
    num[idx] = st[2:]
    idx+=1
 
Gregory = hero(num[0], 'air')
air.append(Gregory)
Donnie = hero(num[1], 'land')
land.append(Donnie)
Bilco = hero(num[2], 'sea')
sea.append(Bilco)
 
un = 3
s = 0
while s < 504:
    rand = random.randint(1,3)
    if rand == 1:
        newbie = solder(num[un], 'воздух')
        air.append(newbie)
        un+=1
        s+=1
    elif rand == 2:
        newbie = solder(num[un], 'земля')
        land.append(newbie)
        un+=1
        s+=1
    elif rand == 3:
        newbie = solder(num[un], 'вода')
        sea.append(newbie)
        un+=1
        s+=1
 
 
A = len(air)
L = len(land)
S = len(sea)
 
print (f'воздух - {A}, земля {L}, вода {S}')
 
if (A>L) and (A>S):
    print(f'силы воздушные победили!')
    rs = random.randint(1, A)
    newbie.myindex(rs)
    newbie.randunit(air[rs].id)
    newbie.follow(Gregory.id)
    Gregory.up()
if (L>A) and (L>S):
    print(f'силы сухопутные победили!')
    rs = random.randint(1, L)
    newbie.myindex(rs)
    newbie.randunit(land[rs].id)
    newbie.follow(Donnie.id)
    Donnie.up()
if (S>L) and (S>A):
    print(f'силы морские победили!')
    rs = random.randint(1, S)
    newbie.myindex(rs)
    newbie.randunit(sea[rs].id)
    newbie.follow(Bilco.id)
    Bilco.up()
 
input('')

Домашнее задание.
import random
 
class Solder(object):
    def __init__(self, number, team):
        self.number = number
        self.team = team
 
    def follow_the_hero(self, hero):
        print("Солдат под номером", self.number, "следует за героем", hero.number)
 
class Hero(Solder):
    def __init__(self, number, team, level):
        Solder.__init__(self, number, team)
        self.level = level
 
    def growth_level(self):
        self.level += 1
        print("У героя", self.number, "повысился уровень")
 
 
s1=[]
s2=[]
h1 = Hero(1, 1, 0)
h2 = Hero(2, 2, 0)
n=2
while n < 22:
    s = Solder(n+1, random.randint(1,2))
    n += 1
    if s.team == 1:
        s1.append(s) 
    elif s.team == 2:
        s2.append(s) 
print("Количество солдат героя", h1.number, "составляет", len(s1),\
      "\nКоличество солдат героя",h2.number, "составляет", len(s2))
if len(s1)>=len(s2):
    h1.growth_level()
    s = random.choice(s1)
    s.follow_the_hero(h1)
else:
    h2.growth_level()
    s = random.choice(s2)
    s.follow_the_hero(h2)

from random import randrange as rnd
 
 
class Human:
    """Общий класс Человек"""
    def __init__(self, name):
        self._uin = rnd(100000, 999999)  # Уникальный номер
        self.name = name  # Имя
 
    def __repr__(self):
        return f"{self.name}-{self.get_uin()}"
 
    def get_uin(self):  # Возвращает уникальный номер
        return self._uin
 
 
class Hero(Human):
    """Класс Герой"""
    lvl_max = 80
 
    def __init__(self, name, team_n, lvl=1):
        super().__init__(name)
        self.team = team_n  # Принадлежность к команде
        if lvl > self.lvl_max:
            lvl = self.lvl_max
        if lvl <= 0:
            lvl = 1
        self.lvl = lvl  # Уровень героя
 
    def __repr__(self):
        return f"Герой: " + super().__repr__() + f" уровень={self.lvl}, команда={self.team}"
 
    def lvl_up(self):  # Метод увеличения уровня героя
        self.lvl += int(self.lvl < self.lvl_max)
 
 
class Soldier(Human):
    """Класс Солдат"""
    def __init__(self, name, team_n):
        super().__init__(name)
        self.team = team_n  # Принадлежность к команде
 
    def __repr__(self):
        return "Солдат: " + super().__repr__()
 
    def follow_hero(self, hero):
        if isinstance(hero, Hero):
            print(f"Я, солдат {self.name}, следую за героем {hero.name}!")
        else:
            print(f"Я, солдат {self.name}, не знаю такого героя.")
 
 
human_name = ["John", "Peter", "Michael", "Jim", "Paul", "Alex"]
team_name = ["красные", "зеленые"]
sold_max = 9  # Максимальное количество солдат в команде
team = dict()
for i in team_name:  # Формируем команды
    team[i] = [Hero(human_name[rnd(len(human_name))], i), []]  # Герои
    for j in range(rnd(1, sold_max+1)):
        team[i][1].append(Soldier(human_name[rnd(len(human_name))], i))  # Солдаты
team_winner_name = None  # Имя команды-победителя
team_winner_len = 0  # Количество солдат в команде-победителе
for i in team_name:  # Выводим длину команд и вычисляем победителя
    x = len(team[i][1])
    print(f"Команда {i} состоит из {x} солдат")
    if x > team_winner_len:
        team_winner_name = i
        team_winner_len = x
print(f"Команда победитель - {team_winner_name}")
team[team_winner_name][0].lvl_up()  # Герой команды-победителя поднимает уровень
num_follow_sold = rnd(team_winner_len)  # Случайный солдат из команды-победителя...
team[team_winner_name][1][num_follow_sold].follow_hero(team[team_winner_name][0])  # ...следует за своим героем
print(team[team_winner_name][0])  # Выводим данные на героя команды-победителя
print(team[team_winner_name][1][num_follow_sold])  # Выводим данные на солдата, который следует за своим героем

from random import randint
 
class Charet:
    def __init__(self, id, fraction):
        self.id = id
        self.fraction = fraction
        if self.fraction == 0:
            del self.fraction
            self.fraction = 'Норки'
        else:
            del self.fraction
            self.fraction = 'Горноры'
 
class Hero(Charet):
    def __init__(self, id, fraction, level = 1):
        Charet.__init__(self, id, fraction)
        self.level = level
 
    def levelUp(self):
        self.level += 1
 
 
 
class Solider(Charet):
    def goHero(self, hero):
        print("{0} Идёт за героем {1} ".format(self.id, hero.id))
 
hero_comand1 = Hero(1, 0)
hero_comand2 = Hero(2, 1)
 
list1 = []
list2 = []
 
i = 0
 
while i < 30:
    sold = Solider(i+3, randint(0,1))
    if sold.fraction == 'Норки':
        list1.append(sold)
        i += 1
    else:
        list2.append(sold)
        i += 1
 
 
print("Команда 1 {0} человек ".format(len(list1)))
print("Команда 2 {0} человек ".format(len(list2)))
 
if len(list1) > len(list2):
    hero_comand1.levelUp()
else:
    hero_comand2.levelUp()
 
list1[4].goHero(hero_comand1)
list2[4].goHero(hero_comand2)

import uuid
import random
 
 
teams = ['blue', 'red']
 
 
class Unit:
    def __init__(self, team):
        self.team = team
        self.id = uuid.uuid1()
 
class Hero(Unit):
    def __init__(self, team):
        Unit.__init__(self, team)
        self.level = 1
 
    def level_up(self):
        self.level += 1
 
 
class Soldier(Unit):
    def __init__(self, team):
        Unit.__init__(self, team)
        self.hero = None
 
    def follow_the_hero(self, hero):
        self.hero = hero
 
 
red_hero = Hero('red')
blue_hero = Hero('blue')
 
red_team = []
blue_team = []
 
for soldier in range(20):
    s = Soldier(random.choice(teams))
    red_team.append(s) if s.team == 'red' else blue_team.append(s)
 
red_hero.level_up() if len(red_team) > len(blue_team) else blue_hero.level_up()
print(f'red team: {len(red_team)} | blue team: {len(blue_team)}')
print(f'red hero: {red_hero.level} | blue hero: {blue_hero.level}')
 
s = random.choice(red_team)
s.follow_the_hero(red_hero)
print(f'red hero: {red_hero.id} | red soldier: {s.id}')

import random
 
class Strategy():
    def __init__(self, number, team):
        self.team = team
        self.number = number
 
 
class Soldier(Strategy):
    def Following_for_hero(self, Hero):
        self.Hero = Hero
        print ('Im following hero!')
 
class Hero(Strategy):
    lvl = 0
    def lvlup(self, ):
        self.lvl += 1
 
Hero_one = Hero(random.random(), 1)
Hero_two = Hero(random.random(), 2)
 
first_team = []
second_team = []
 
for i in range(10):
    team_for_soldier = random.randint(1, 3)
    number_for_soldier = random.random()
 
    if team_for_soldier == 1:
        Voin = Soldier(number_for_soldier, team_for_soldier)
        first_team.append(Voin)
    else:
        Voin = Soldier(number_for_soldier, team_for_soldier)
        second_team.append(Voin)
 
print (len(first_team), len(second_team))
 
 
if len(first_team) > len(second_team):
    Hero_one.lvlup()
elif len(first_team) == len(second_team):
    print ("DRAW !!!")    #В случае одинаковом кол-ве солдат в списке
elif len(first_team) == 0 or len(second_team) == 0:
    print ('CLEAN VICTORY!')     #В случае "сухой" победы
else:
    Hero_two.lvlup()
 
print ('Level Hero\'s One:' ,Hero_one.lvl,'\n'
       'Level Hero\'s Two:' ,Hero_two.lvl,'\n')
 
if len(first_team) != 0:    #сделано что бы в случае отсутсвия солдат в списке №1 не было ошибки
    Follow_command = first_team[0].Following_for_hero(Hero_one)
    print ('Hero one Number:', Hero_one.number,'\n'   #Идентификационный номер героя
           'Soldier\'s Number:', first_team[0].number    #Идентификационный номер солдата(в данном случае на первой позиции в списке), который следует за данным героем
           )
Всё работает. Подскажите, что можно сделать что бы код был более чистым ? Если такое возможно, в общем, жду критики. В особенности интересует в начале кода при создании классов и объектов Спасибо :)

Скажите, зачем в методе setPlaces торчит параметр "р", если все данные он берёт от родителя? Я к этому аргументу даже обратиться не могу. IDE-шка меня сразу на три буквы посылает. Или по другому, как передать данные в этот арумент?

import random
 
class Unit:
 
	def __init__(self, id, name_team):
		self.id = id
		self.name_team = name_team
 
class Hero(Unit):
 
	def __init__(self, id, name_team, level=1):
		Unit.__init__(self, id, name_team)
		self.level = level
 
	def level_up(self):
		self.level += 1
 
class Solgier(Unit):
 
	def go_to_hero(self, obj):
		if self.name_team == obj.name_team:
			print "I'm soldat, my id = {x}. I go to my hero. His id = {y}".format(x=self.id, y=obj.id)
 
def my_main():
 
	hero1 = Hero(101, "vasilianstvo")
	print "Created hero. His id - ", hero1.id
	hero2 = Hero(102, "valerianstvo", 2)
	print "Created hero. His id - ", hero2.id
 
	sol1 = []
	sol2 = []
 
	for element in xrange(0, 15):
		index = random.randint(1, 100)
		if index < 50:
			sol1.append(Solgier(index, "vasilianstvo"))
		else: sol2.append(Solgier(index, "valerianstvo"))
 
	if len(sol1) > len(sol2):
		hero1.level_up()
		print "Hero level-up with comand 'vasilianstvo'. His level - ", hero1.level
	else:
		hero2.level_up()
		print "Hero level-up with comand 'valerianstvo'. His level - ", hero2.level
 
 
	num_soldier = hero1.level - hero2.level
	if num_soldier <= 0:
		num_soldier = abs(num_soldier) + 1
 
	for soldats in xrange(0,num_soldier):
		if hero1.level < hero2.level:
			sol1[soldats].go_to_hero(hero1)
		elif hero1.level > hero2.level:
			sol2[soldats].go_to_hero(hero2)
 
	raw_input()
 
my_main()

from random import randint
Q=int(input('Введите количество солдат:\n'))
Team1=[]
Team2=[]
i=9
class Hero:
  def __init__(self,number,team,level=1):
    self.number=number
    self.team=team
    self.level=level
  def levelup(self):
    self.level+=1
    print(f'Герой {self.number} увеличил уровень до {self.level}')
class Soldat(Hero):
  def following(self,H):
    self.H=H.number
    print(f'Солдат с индексом {self.number} следует за {self.H}')
Hero1=Hero(1,'1')
Hero2=Hero(2,'2')
while len(Team1)+len(Team2)<Q:
  i+=1
  S='S'+str(i)
  A=randint(0,1)
  S=Soldat(i,str(A))
  if A==0:
    Team1.append(S)
  else:
    Team2.append(S)
if len(Team1)>=len(Team2):
  Hero1.levelup()
else:
  Hero2.levelup()
B=randint(0,len(Team2)-1)
Team1[B].following(Hero1)

import random
 
class Units:
    def __init__(self,id_name):
        self.id_name=id_name
 
class Hero(Units):
    def __init__(self,id_name,listed,lvl=1):
        Units.__init__(self,id_name)
        self.listed=[]
        self.lvl=lvl
 
    def upgrade(self,hero):
        hero.lvl+=1
        print('У {} повысился уровень. Теперь он равен: {}.'.format(hero.id_name,hero.lvl))
 
class Soldier(Units):    
    def follow(self,hero,soldier):        
        hero.listed.append(soldier)
 
hero1=Hero('id2323',[])
hero2=Hero('id7274',[])
commands=[hero1,hero2]
 
def create():
    for i in range(20):        
        soldier=Soldier('%s'%random.randint(1,9999))                        
        soldier.follow(random.choice(commands),soldier)
 
def how_many():
    print('У первого героя:',len((hero1.listed)))
    print('У второго героя',len((hero2.listed)))
 
    if len(hero1.listed) > len(hero2.listed): #Перебросить солдата
        warrior=random.choice(hero2.listed)
        try:
            hero1.listed.append(warrior)
            hero2.listed.remove(warrior)
            hero1.upgrade(hero1)
            print("Уникальный номер солдата: {}. Уникальный номер Героя: {} ".format(warrior.id_name, hero1.id_name))
        except:
            print('У одного из героев 0 воинов')
 
    elif len(hero1.listed) < len(hero2.listed): #Перебросить солдата
        warrior=random.choice(hero1.listed)
        try:
            hero2.listed.append(warrior)
            hero1.listed.remove(warrior)
            hero2.upgrade(hero2)
            print("Уникальный номер солдата: {}. Уникальный номер Героя: {} ".format(warrior.id_name, hero2.id_name))
        except:
            print('У одного из героев 0 воинов')
    else:
        print('Одинаковое количество в каждой команде, начинаем заново')
        hero1.listed.clear()
        hero2.listed.clear()
        create()
        how_many()
 
    print('Теперь у первого героя {} воинов, а у второго {} воинов.'.format(len(hero1.listed),len(hero2.listed)))
 
create()    
how_many()
 
#Код дополнен сменой воина проигравшего героя выигравшему.

from itertools import count
from random import randint
 
class Unit():
    ids = count(1)
    def __init__(self, team=0):
        self.id = next(self.ids)
        if not team:
            self.team = randint(1,2)
        else:
            self.team = team
 
    def __repr__(self):
        return f'{self.__class__.__name__}(id={self.id})'
 
class Hero(Unit):
    level = 0
    def level_up(self, delta=0):
        self.level += delta
 
class Soldier(Unit):
    my_hero = None
    def follow_hero(self, hero_obj):
        self.my_hero = hero_obj
 
# Создаем героев и отправляем Alex в команду №1, Bob в команду №2
Alex = Hero(1)
Bob = Hero(2)
 
# Alex в отряде №1, Bob в отряде №2
troop1, troop2 = [Alex], [Bob]
 
# Создаем солдат и раскидываем по отрядам 
#for soldier in map(Soldier, range(10)):
for soldier in (Soldier() for _ in range(20)):
    troop1.append(soldier) if soldier.team == 1 else troop2.append(soldier)
 
# Поднимааем уровень тому герою, у кого отряд больше.
Alex.level_up(len(troop1) > len(troop2)) 
Bob.level_up(len(troop1) < len(troop2)) 
 
# Отправляем случайного солдата из первого отряда следовать за героем из того же отряда
troop1[randint(1, len(troop1)-1)].follow_hero(Alex)
 
# Смотрим, у кого больше солдат
print(f'{Alex} has a troop of {len(troop1)-1} soldiers')
print(f'{Bob} has a troop of {len(troop2)-1} soldiers')
 
# Смотрим, у кого из героев больше уровень
print(f'{Alex} has level {Alex.level}')
print(f'{Bob} has level {Bob.level}')
 
# Смотрим, какой солдат следует за первым героем
for soldier in troop1[1:]:
    if soldier.my_hero:
        print(f'{soldier} follows by {soldier.my_hero}')

import random
class Gamers:
    def __init__(self, idg, ct):
        self.idg=idg  # object number
        self.ct=ct  # comand type
# 1 - team1
# 2 - team2
class Soldier(Gamers):
    def goHero(self, hero):
       print('Солдат c id: '+str(self.idg)+' проследовал за героем: '+str(hero.idg))
 
 
class Hero(Gamers):
    def __init__(self, idg, ct, level): #переопределяем конструктор, добавляем параметр level
        Gamers.__init__(self, idg, ct)
        self.level=level
 
    def levelUp(self): #метод увеличиващий level на 1
        self.level=self.level+1
 
 
h1= Hero(1,1,0) #создаем героя, для первой команды
h2= Hero(2,2,0) #создаем героя, для второй команды
 
team1=[] #создаем список куда будут вноситься солдаты первой команды
team2=[] #создаем список куда будут вноситься солдаты второй команды
 
k=2 # т.к. у нас уже есть 2 героя с id=0 и id=1, то id солдатов будет начинаться с 2
for i in range (10): #создаем цикл в котором будет создано 10 солдат
    sol = Soldier(k+1, random.randint(1,2)) # создаем солдата с рандомной принадлежностью к команде
    k=k+1 # увеличиваем счетчик id на 1
    print (sol.idg, sol.ct) #выводим данные по вновь созданному солдату 
    if sol.ct==1: # определяем в какой список отнести солдата, если параметр ct =1, то 
        team1.append(sol) # записываем в список первой команды
    else:
        team2.append(sol) # если же параметр ct =2, то во вторую команду
 
if len(team1)>len(team2): # если в 1й команде больше солдат, то
    h1.levelUp() # увеличим level героя 1
    print ('Hero1 has level = '+str(h1.level))
elif len(team1)==len(team2): # если в командах равное кол-во солдат, выведем об этом сообщение
    print('Both teams has the same coldiers numbers')
else: #в противном случае во второй команде больше солдат
    h2.levelUp() #увеличим level для героя 2
    print('Hero2 has level = '+str(h2.level))
 
# для выбора рандомного солдата из первой команды: 
a=len(team1) #определим длину первой команды
randomSol=random.randint(0,a-1) # выберем рандомного солдата, но помним, что в списке нумерация начинается с 0, значит и длина списка на 1 меньше
print ('в первой команде ' +str(a) +' солдатов')
print ('Выбран ' +str(randomSol) +' элемент в списке')
team1[randomSol].goHero(h1) #вызовем метод "следовать за героем" для рандомного солдата из первой команды

Ответ на от Fanciful

# поправка для предыдущего решения:
h1= Hero(0,1,0) #создаем героя, для первой команды
h2= Hero(1,2,0) #создаем героя, для второй команды

Очень долго ломал голову как это сделать, потом перечитывал все коментарии. В итоге слепил это) Как то очень тяжело дается ООП...
import random
 
 
class Unit:
    def __init__(self, id, team):
        self.id = id
        self.team = team
 
 
class Hero(Unit):
    lvl = 0
 
    def lvl_up(self, lvl):
        self.lvl += lvl
 
 
class Solder(Unit):
    def follow(self, hero):
        print("Solder with ID: {} follow to the {} hero".format(self.id, hero))
 
 
hero_1 = Hero("First", 1)
hero_2 = Hero("Second", 2)
team_1 = []
team_2 = []
for i in range(int(input("How much solder?: "))):
    j = round(random.random(), 2)
    if j < 0.5:
        i = Solder(j, 1)
        team_1.append(i)
    else:
        i = Solder(j, 2)
        team_2.append(i)
print("Number of warriors of the first hero:", len(team_1))
print("Number of warriors of the second hero:", len(team_2))
if (len(team_1)) > (len(team_2)):
    hero_1.lvl_up(1)
else:
    hero_2.lvl_up(1)
 
print("First hero level:", hero_1.lvl)
print("Second hero level:", hero_2.lvl)
team_2[0].follow(hero_1.id)

from random import randint
 
class Human:#common class
    def __init__(self, number, team):
        self.number = number
        self.team = team
 
 
class Hero(Human):# class hero
    def __init__(self, level, number, team):
        Human.__init__(self, number, team)
        self.level = level
 
    def level_up(self):#func level up
        self.level += 1
 
 
class Warrior(Human):#warrior class
    def follow_for_hero(self, hero):
        print ("I'm Follow for my hero!")
 
 
Hero_one = Hero(1, 1, 1)#hero 1
Hero_two = Hero(1, 2, 2)#hero 2
 
 
list_with_team_one = []#list with warriors team #1
list_with_team_two = []#list with warriors team #2
 
 
for i in range(11):
    t = randint(1, 2)
    if t == 1:
        war_1 = Warrior(randint(1, 1000), t)
        list_with_team_one.append(war_1)
    elif t == 2:
        war_2 = Warrior(randint(1, 1000), t)
        list_with_team_two.append(war_2)
 
 
length_with_team_1 = len(list_with_team_one)
length_with_team_2 = len(list_with_team_two)
print ('Team one have ' + str(length_with_team_1) + ' units! and team two have ' + str(length_with_team_2) + ' units!')
 
 
if length_with_team_1 > length_with_team_2:
    Hero_one.level_up()
    print ('HERO ONE LEVEL UP! NOW HE ARE AT LEVEL: ' + str(Hero_one.level))
else:
    Hero_two.level_up()
    print ('HERO TWO LEVEL UP! NOW HE ARE AT LEVEL: ' + str(Hero_two.level))
 
print ('Hero takes one warrior with him!')
 
war_with_one = randint(0, length_with_team_1)#random number for random warrior from list
if war_with_one > 0:
    war_with_one -= 1
number_of_warrior = list_with_team_one[war_with_one]#get this warrior from list
print ('Hero with number: ' + str(Hero_one.number) + ' takes warrior with number: ' + str(number_of_warrior.number))
Все работает и все по заданию, за исключение момента когда в первом отряде нету воинов, тогда вылезает исключение, не стал писать try/except на последние строки, извините )

Автор разве так можно издеваться? Разбирал материал на твоих примерах из статьи и не мог понять почему ловил ошибку AttributeError! У тебя опечатка - вместо length - должно быть lenght. AttributeError: 'KitchenTable' object has no attribute 'length' Новичку можно психику сломать с такими опечатками)

#Мой вариант:
 
import random
 
class Person():
	def __init__(self,id,team=random.randint(0,1)):#
		self.id=id
		self.team=team
 
class Solder(Person):
	def follow(self,hero):
		print('Солдат ',self.id,' следует за героем ',hero)
 
class Hero(Person):
	lvl=1
	def lavel(self,lvl):
		self.lvl= self.lvl+random.randint(1,3)
		return self.lvl
 
hero1=Hero(1,0)
hero2=Hero(2,1)
 
print('Герой1 находится в команде с номером: ',hero1.team,'и имеет уровень: ',hero1.lvl)
 
print('Герой2 находится в команде с номером: ',hero2.team,'и имеет уровень: ',hero2.lvl)
 
print('\n++++++++++++++++++++++++++++++++\n')
 
list_team1=[]
list_team2=[]
 
for i in range(3,random.randint(5,20)):#диапозон чисел  от 1 и до рамдомной цифры равной от 5 до 20
	solder=Solder(i,random.randint(0,1))# солдату рандомно присваивается команда (0 или 1)
	if solder.team==0:
		list_team1.append(solder.id)
	elif solder.team==1:
		list_team2.append(solder.id)
	i+=1
 
print('Номера солдат в команде с номером 0:\n ',list_team1)
print('Номера солдат в команде с номером 1:\n ',list_team2)
 
print('\n++++++++++++++++++++++++++++++++\n')
 
if len(list_team1)>len(list_team2):
	print('Т.к. в команде с номером 0 количество солдат больше чем в команде с номером 1, то уровень Героя1 увеличивается и теперь составляет: ',hero1.lavel(1))
 
elif len(list_team1)<len(list_team2):
	print('Т.к. в команде с номером 1 количество солдат больше чем в команде с номером 0, то уровень Героя2 увеличивается и теперь составляет: ',hero1.lavel(1))
 
else:
	print('Т.к в обоих командах одинаковое число солдат - всё останется неизменным.')
 
list_team1[0].follow(hero1.id)#первый солдат из первого списка идёт за первым героем. 
Не понимаю, почему появляется сообщение ‘int’ object has no attribute ‘follow’? И как решить эту проблему?

Ответ на от Xp

Вопрос: Почему не наследуется team из Супет-класса при создании солдата? И пожалуйста, ответьте на предыдущий вопрос.
class Person:
    def __init__(self,team=random.randint(0,1)):
        self.team=team
 
class Hero(Person):
    def __init__(self,id,team,level=80):
        Person.__init__(self,team)
        self.heroid=id
        self.level=level
 
    def levelup(self):
        self.level+=10
 
class Solder(Person):
    def __init__(self,id,team):
        Person.__init__(self,team)
        self.solderid=id
 
    def go_for_hero(self):
        return self.heroid
 
 
#В основной ветке программы создается по одному герою для каждой команды.    
hero1=Hero(1,0)#герой с id 1 из команды 0 
hero2=Hero(2,1)#герой с id 2 из команды 1
 
#В цикле генерируются объекты-солдаты. Их принадлежность команде определяется
#случайно. Солдаты разных команд добавляются в разные списки.
 
#Создаём пустые списки команд для солдат:
list_team1=[]
list_team2=[]
for i in range(3,random.randint(4,20)):#формируем рандомно кол-во солдат (диапозон от 3
                                       #(т.к. i записывается в id) и рандомного числа)
    solder=Solder(i)#создаётся солдат, его команда формируется рандомно - либо 0, либо 1, но почему то это не
                    #наследуется из Супер-класса (Person), где team задано по умолчанию.
    if solder.team==0:
        list_team1.append(solder.solderid)
    if solder.team==1:
        list_team2.append(solder.solderid)
    i+=1

from random import randint
 
class Unit():
    def __init__(self, team, number):
        self.team=team
        self.number=number
class Hero(Unit):
    def __init__(self, team, number,level,name):
        self.team=team
        self.number=number
        self.level=level
        self.name=name
    def go_team(self,a):
        print('V pohod poshel comandir',self.name,' i boec nomer ', a[-2])
 
 
 
 
 
h1=Hero(1,1000,0,'Ivan')
h2=Hero(2,2000,0,'Stepan')
a=int(input('Введите число солдат которые нужно создать: \n'))
o1=[]
o2=[]
o1.append(h1.number)
o2.append(h2.number)
for i in range(a):
    command=randint(1,2)
    number=randint(0,1000)
    print(command)
    if number not in o1 and number not in o2:
        if command%2 == 0:
            o1.append(number)
            print('В команду 1 добавился игрок с номером ',number,"теперь в ней стало ",len(o1),"игроков")
            if len(o1)>len(o2):
                h1.level+=1
                print('Уровень героя 1 поднялся и стал',h1.level)
        elif command%2 == 1:
            o2.append(number)
            print('В команду 2 добавился игрок с номером ',number,"теперь в ней стало ",len(o1),"игроков")
            print('Создание команд окончено')
            if len(o2)>len(o1):
                h2.level+=1
                print('Уровень героя 2 поднялся и стал',h2.level)
 
print('Создание команд окончено\n В комманде 1 всего', len(o1),' бойцов и во главе командир ',h1.name," с уровнем" ,h1.level)
print('\n В комманде 2 всего', len(o2),' бойцов и во главе командир ',h2.name," с уровнем" ,h2.level)
 
h2.go_team(o2)

Объясните пожалуйста дополнение методов при условии, что у конструктора родительского класса, атрибуты (параметры) заданы по-умолчанию. Например:
class Person:
	def __init__(self,x=5):
		self.x=x
 
class unit(Person):
	def __init__(self,y,x):
		Person.__init__(self,x)
		self.y=y
 
	def info(self):
		return self.y, self.x
 
h=unit(7)
print(h.info())
При создании объекта h не наследуется поле x, которое по-умолчанию имеет значение 5. Появляется ошибка о том, что __init__() требуется аргумент x. Но из предыдущей главы мы знаем, что: Если класс вызывается без значений в скобках, то для параметров будут использованы их значения по умолчанию. Здесь этого не происходит.

Ответ на от Xp

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

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

Ответ на от plustilino

Спасибо!
Т.е. вот так будет правильно?:
class unit(Person):
	def __init__(self,y):
		Person.__init__(self,5)
		self.y=y
(По крайней мере код работает)
Попробовал сюда подставить другие числовые литералы, и т.о. происходит переопределение x.

Ответ на от Xp

Это не правило, но с практической точки зрения лучше, когда у конструкторов и родительского и дочернего классов одинаковое число параметров. Бывает, что объекты разных родственных классов создаются или обрабатываются в одном цикле, т. е. по одному алгоритму. При этом у них должны быть одинаковые "интерфейсы". 

# https://younglinux.info/oopython/inheritance.php
 
class Warrior:
    def __init__(self, team, hero=None):
        self.id = id(self)
        self.team = team
        self.hero = hero
        team.append(self)
 
    def __str__(self):
        s = f'warrior, id: {str(self.id)}'
        if self.hero:
            s += f', hero: {self.hero.name}'
        return s
 
    def follow_hero(self, hero):
        self.hero = hero
 
 
class Hero(Warrior):
    def __init__(self, team, name, level=1):
        Warrior.__init__(self, team)
        self.name = name
        self.level = level
 
    def __str__(self):
        return f'hero {self.name}, id: {str(self.id)}, level: {self.level}'
 
    def inc_level(self, value=1):
        self.level += value
 
 
def main():
    import random
 
    british_team = []
    german_team = []
 
    british_hero = Hero(british_team, 'Richard the Lionheart')
    german_hero = Hero(german_team, 'Otto von Bismarck')
 
    warriors_qty = random.randrange(1,10)
    for i in range(warriors_qty):
        if random.randrange(2):
            warrior = Warrior(british_team)
        else:
            warrior = Warrior(german_team)
 
    print("\nBritish team:")
    for w in british_team:
        print(w)
 
    print("\nGerman team:")
    for w in german_team:
        print(w)
 
    if len(british_hero.team) > len(german_hero.team):
        british_hero.inc_level()
    elif len(british_hero.team) < len(german_hero.team):
        german_hero.inc_level()
 
    print('\nNew heroes info:')
    print(british_hero)
    print(german_hero)
    print()
 
    british_warrior = british_team[1]
    german_warrior = german_team[1]
 
    british_warrior.follow_hero(british_hero)
    print(british_warrior)
 
    german_warrior.follow_hero(german_hero)
    print(german_warrior)
 
 
if __name__ == '__main__':
    main()

Мое очень простое решение
import random
 
processed = []
team_list = ['blue', 'red']
 
team1 = []
team2 = []
 
 
def rand():
    while True:
        r = random.randint(1, 101)
        if r not in processed:
            processed.append(r)
            return r
 
 
def rand_team():
    return random.choice(team_list)
 
 
class Person:
 
    def __init__(self, team=None):
        self.number = rand()
        self.team = team or rand_team()
 
 
class Hero(Person):
    lvl = 0
 
    def lvl_up(self):
        self.lvl += 1
 
 
class Soldier(Person):
 
    def follow(self, hero):
        print('i follow ' + hero)
 
 
hero1 = Hero('blue')
hero2 = Hero('red')
 
for i in range(11):
    sol = Soldier()
    if sol.team == 'blue':
        team1.append(sol)
    else:
        team2.append(sol)
 
if len(team1) > len(team2):
    hero1.lvl_up()
else:
    hero2.lvl_up()
 
soldat = random.choice(team1)
soldat.follow(hero1.__class__.__name__)
print(hero1.number, soldat.number)

Я хотел добавить возможность просмотра формальной базы данных для получения информации о каждом солдате (имя/id/army),но мне показалось это будет лишним (на самом деле просто лень),т.к. суть задания состоит немного в другом... Собственно...сам код:
import uuid
from random import*
 
import itertools
import time
import sys
 
print(end='\n'*3)
 
def Loading(): # Эксперементальная симуляция загрузки...забавы ради :)
	it = itertools.cycle(['...|'] +['\b\b\b\b']+['.../']+['\b\b\b\b']+['...-']+['\b\b\b\b']+['...\\']+['\b\b\b\b'])
	print('Loading ', end='')
	for x in range(57):
		time.sleep(0.03)  # выполнение функции
		if x != 56:
		    print(next(it), end='', flush=True)
		elif x == 56:
		    print(next(it), end='\b\b\b\b :)   ', flush=True)
 
 
def conclusion(M,n=0.01): # Фу-ция позволяет последовательно выводить
						  # символы указанной строки, внутри списка
	M=''.join(M)		  # с заданной скоростью (по умолчанию 1 санти-сек.).
	M=list(M)
 
	for i in M:
		print(''.join(i),end='')
		sys.stdout.flush()
		time.sleep(n)
	return ''
 
Loading() # ЗАГРУЗКА................................
 
class Person:
	def __init__(self, z):
		self.id = uuid.uuid1() 
		self.command = z
 
class Hero(Person):
	def __init__(self, z):
		Person.__init__(self, z)
		self.level = 1
	def upLevel(self):
		self.level += 1
 
class Soldier(Person):
	def __init__(self, z):
		Person.__init__(self, z)
		self.follow_hero = None
	def follow(self, hero):
		self.follow_hero = hero.id
	def get_follow(self):
		return self.follow_hero
 
hero1 = Hero('Red')
hero2 = Hero('White')
 
Red_army= []    # Те самые списки в которых хранятся наши объекты. :)
White_army = []
 
 
for i in range(30):
	f = randint(100,900)
	if f % 2 == 0:
		White_army.append(Soldier('Blue'))
	else:
		Red_army.append(Soldier('Red'))
 
print(end='\n'*3)
 
 
print('Объекты, (солдаты) "Белой" армии:',end='\n\n')
n=1
for i in White_army:	
	if n < 10:
		print(i,'[',n,' ]')
	elif n>=10:
		print(i,'[',n,']')
	n+=1
	time.sleep(0.017)
 
print(end='\n'*2)
 
 
print('Объекты, (солдаты) "Красной" армии:',end='\n\n') 
z=1
for i in Red_army:
	if z < 10:
		print(i,'[',z,' ]')
	elif z>=10:
		print(i,'[',z,']')
	z+=1
	time.sleep(0.017)	
 
if len(Red_army) > len(White_army):
	print(end='\n'*2)
	Loading() # ЗАГРУЗКА................................
	print(end='\n'*2)
	hero1.upLevel()
	print(conclusion('Кол-во солдат (объектов) в "Белой" армии:'), len(White_army),end='.\n')
	print(conclusion('Кол-во солдат (объектов) в "Красной" армии:'),len(Red_army),end='.\n\n')
 
	print(conclusion('Красная армия одержала ПОБЕДУ!'))
	print(conclusion('Уровень героя hero1 повысился на +1.'))
	print(conclusion('Уровень героя ='),hero1.level,end='.')
	Red_army[0].follow(hero1)
	print(end='\n')
	print(conclusion('Красная армия, следуем \
		\nза героем с ID'),Red_army[0].get_follow(),'!!!')
	print(end='\n')
	print(conclusion('ID hero1='),hero1.id,end='.\n\n')
elif len(Red_army) < len(White_army):
	print(end='\n'*2)
	Loading() # ЗАГРУЗКА................................
	print(end='\n'*2)
	hero2.upLevel()
	print(conclusion('Кол-во солдат (объектов) в "Белой" армии:'), len(White_army),end='.\n')
	print(conclusion('Кол-во солдат (объектов) в "Красной" армии:'),len(Red_army),end='.\n\n')
 
	print(conclusion('"Белая" армия одержала ПОБЕДУ!'))
	print(conclusion('Уровень героя hero2 повысился на +1.'))
	print(conclusion('Уровень героя ='),hero2.level,end='.')
	White_army[0].follow(hero2)
	print(end='\n')
	print(conclusion('"Белая армия", следуем \
		\nза героем с ID'),White_army[0].get_follow(),'!!!')
	print(end='\n')
	print(conclusion('ID hero2 ='),hero2.id,end='.\n\n')
else:
	print(end='\n')
	print(conclusion('Кол-во солдат (объектов) в "Белой" армии:'), len(White_army),end='.\n')
	print(conclusion('Кол-во солдат (объектов) в "Красной" армии:'),len(Red_army),end='.\n')
	print(conclusion(['НИЧЬЯ !!!']),end='.\n\n')
 
Loading()
 
print(end='\n\n')
 
print('Программа завершена.')
 
print(end='\n'*3)

import random as r
 
 
class Game:
    def __init__(self, name, flag):
        self.name = name
        self.flag = flag
 
 
class Hero(Game):
    def __init__(self, name, flag, lvl=1):
        super().__init__(name, flag)
        self.lvl = lvl
        self.squad = []
 
    def level_up(self):
        self.lvl += 1
        print(f'Герой {self.name} получает уровень {self.lvl}')
 
    def append(self, obj):
        self.squad.append(obj)
 
    def __len__(self):
        return len(self.squad)
 
    def __eq__(self, other):
        return len(self) == len(other)
 
    def __lt__(self, other):
        return len(self) < len(other)
 
 
class Soldier(Game):
    def __init__(self, name, flag):
        super().__init__(name, flag)
        self.name = id(self)
 
    def follow_the_hero(self, hero):
        if self.flag == hero.flag:
            print(f'Солдат номер {self.name} следует за {hero.name}')
        else:
            print(f'Я {self.name} солдат своего Отечества и я скорее умру, чем примкну к стану врага')
 
 
super_1 = Hero('One', True)
super_2 = Hero('First', False)
 
soldier = Soldier(None, True)
soldier.follow_the_hero(super_1)
 
while True:
 
    for i in range(99):
        soldier = Soldier(None, r.randint(1, 100) < 50)
        if soldier.flag:
            super_1.append(soldier)
        else:
            super_2.append(soldier)
 
    max(super_1, super_2).level_up()
 
    for elem in super_1, super_2:
        elem.squad.clear()
 
    if input('Нажмите Ввод для продолжения\nВведите любой символ для завершения программы\n'):
        break
 
print(f'Итог:\n'
      f'Герой {super_1.name} уровень {super_1.lvl}\n'
      f'Герой {super_2.name} уровень {super_2.lvl}')

Хорошее упражнение. Посидел, поразбирался.
#ооп урок 3
#подключаем модуль random
import random
#определяем классы
#
#юнит(главный класс)
class Unit:
	def __init__(self, id, team):
		self.id = id
		self.team = team
#герой
class Hero(Unit):
	def __init__(self, id, team, level=1):
		Unit.__init__(self, id, team)
		self.level = level
	def levelUp(self):
		self.level = self.level + 1
		return(self.level)
#солдат
class Soldier(Unit):
	def follow(self, hero):
		print("Я, солдат id {}, следую за героем id {}".format(self.id, hero))
#скрипт
#
#создаем по одному герою каждой команды
hero_red = Hero("100", "red")
hero_blue = Hero("200", "blue")
#список id солдат
soldier_id = ["10", "11", "12", "13", "14", "15", "16"]
#списки солдат в командах "red" и "blue"
red = []
blue = []
#создаем солдатов
index = 0
for i in soldier_id:
	#случайный выбор команды
	choice_team = random.choice(["red", "blue"])
	#создаем солдата
	i = Soldier (soldier_id[index], choice_team)
	#заносим в список нужной команды
	if choice_team == "red":
		red.append(i)
	if choice_team == "blue":
		blue.append(i)
	#увеличиваем индекс списка id
	index = index+1
#выводим кол-во солдат в командах
print("Кол-во солдатов команды Red:{}".format(len(red)))
print("Кол-во солдатов команды Blue:{}".format(len(blue)))
#сравниваем списки команд
#если red больше
if len(red) > len(blue):
	print("Герой команды Red(id:{}) получил {} уровень".format(hero_red.id, hero_red.levelUp()))
#если blue больше
if len(red) < len(blue):
	print("Герой команды Blue(id:{}) получил {} уровень".format(hero_blue.id, hero_blue.levelUp()))
#выбираем случайного солдата из red
#он следует за своим героем
(random.choice(red)).follow(hero_red.id)

from random import randrange
 
class Person:
    id = 0
    team = None
 
class Hero(Person):
    def __init__(self, team, lvl ):
        Hero.id = Hero.id + 1
        self.lvl = lvl
        self.team = team
 
    def up_lvl(self):
        self.lvl = self.lvl + 1
 
class Soldier(Person):
    def __init__(self, team):
        Soldier.id = Soldier.id + 1
        self.team = team
 
    def to_hero(self, hero):
        return self.id, hero.id
 
def gen_team(num):
    return f'team_{num}'
 
a = Hero('team_1', 1)
b = Hero('team_2', 2)
team = {}
for item in range(int(input('Enter the number of soldiers: '))):
    soldier = Soldier(gen_team(randrange(1,3)))
    lst = team.get(soldier.team, [])
    lst.append(soldier)
    team[soldier.team] = lst
 
result = "team_{}: {} soldiers"
soldiers_number_1 = len(team['team_1'])
soldiers_number_2 = len(team['team_2'])
print(result.format(1, soldiers_number_1))
print(result.format(2, soldiers_number_2))
 
if soldiers_number_1 > soldiers_number_2:
    a.up_lvl()
else:
    b.up_lvl()
 
soldier = team['team_1'][randrange(0, soldiers_number_1)]
print(soldier.to_hero(a))

import random
import string
 
class Person:
	def __init__(self, id_, team_):
		self.id = id_
		self.team = team_
 
class Hero(Person):
	def __init__(self, id_, team_, name_ = 'No name', lvl_ = 1):
		Person.__init__(self, id_, team_)
		self.name = name_
		self.lvl = lvl_
 
	def upLevel(self):
		self.lvl += 1
 
class Soldier(Person):
	def __init__(self, id_, team_, size = 4):
		Person.__init__(self, id_, team_)
 
		# Присвоение имени
		letters = string.ascii_letters
		self.name = ''.join(random.choice(letters) for i in range(size))
 
	def goToHero(self, hero):
		print('id hero: {0}\nid soldier: {1}'.format(hero.id, self.id))
 
	def getInfo(self):
		return f'#{self.team}, id: {self.id}, name: {self.name}'
 
if __name__ == "__main__":
	hero1 = Hero(1234, 0, 'Igor')
	hero2 = Hero(4321, 1, 'Artem')
 
	soldiers1 = []
	soldiers2 = []
	for i in range(10):
		s = Soldier(
			random.randint(1000, 5000), # id
			random.randint(0, 1), 	    # team
			random.randint(4, 10)	    # name length
		)
 
		if s.team == 0:
			soldiers1.append(s)
		else:
			soldiers2.append(s)
 
 
	# for soldier in soldiers1:
	# 	print(soldier.getInfo())
 
	print('#0:', len(soldiers1), '\n#1:', len(soldiers2))
	print()
 
	if len(soldiers1) > len(soldiers2):
		hero1.upLevel()
	else:
		hero2.upLevel()
 
	soldiers1[random.randint(0, len(soldiers1) - 1)].goToHero(hero1) 

from random import randint
 
sunny, cloudy, rainy = [], [], []
teams = [sunny, cloudy, rainy]
d = {'sunny': sunny, 'cloudy': cloudy, 'rainy': rainy}
 
 
class Players:
 
    id = 1
 
    def __init__(self, team):
        self.id = Players.id
        Players.id += 1
        self.team = team
 
    def get_id(self):
        return self.id
 
 
class Heroes(Players):
 
    def __init__(self, team, level=1):
        Players.__init__(self, team)
        self.level = level
 
    def level_up(self):
        self.level += 1
        return f'\nHero of the team {self.team.title()} is now level {self.level}.'
 
    def add_soldier(self):
        self.team.append(Soldiers(self.team))
 
    def __str__(self):
        return f'Hero {self.team}'
 
 
class Soldiers(Players):
 
    def __str__(self):
        return f'Soldier {self.id}'
 
    def follow_hero(self, hero):
        return f"Soldier id {str(self.id).zfill(3)} following hero from a team {hero.team.title()} with id {str(hero.id).zfill(3)}"
 
 
hero_1 = Heroes('sunny')
hero_2 = Heroes('cloudy')
hero_3 = Heroes('rainy')
hero_di = {hero_1: sunny, hero_2: cloudy, hero_3: rainy}
 
for i in range(int(input('количество солдат: '))):
 
    x = randint(1, len(teams))
    teams[x-1].append(Soldiers(teams[x-1]))
 
heroes_n = [i for i in sorted(hero_di, key=lambda k: len(hero_di[k]), reverse=True)]
teams_n = [i for i in sorted(d, key=lambda k: len(d[k]), reverse=True)]
 
print()
for i in range(len(teams)):
    print(f'Team {teams_n[i].title()}: {len(d[teams_n[i]])} soldiers')
 
print(heroes_n[0].level_up())
print()
print(hero_di[heroes_n[0]][randint(0, len(hero_di[heroes_n[0]]))].follow_hero(heroes_n[0]))