Почему мы используем init в классах Python?



у меня возникли проблемы с пониманием инициализации классов.



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



вот пример:



class crawler:
# Initialize the crawler with the name of database
def __init__(self,dbname):
self.con=sqlite.connect(dbname)

def __del__(self):
self.con.close()

def dbcommit(self):
self.con.commit()


или другой пример кода:



class bicluster:
def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
self.left=left
self.right=right
self.vec=vec
self.id=id
self.distance=distance


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

593   8  

8 ответов:

из того, что вы написали, вы упускаете критическую часть понимания: разницу между классом и объектом. __init__ не инициализирует класс, он инициализирует экземпляр класса или объекта. Каждая собака имеет цвета, но собак как класса нет. Каждая собака имеет четыре или меньше ноги, но класс собаки не. Классе является понятие объекта. Когда вы видите Фидо и спота, вы признаете их сходство, их собачье достоинство. Вот это класс.

когда вы скажи

class Dog:
    def __init__(self, legs, colour):
        self.legs = legs
        self.colour = colour

fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")

вы говорите, Фидо-коричневая собака с 4 ногами, в то время как пятно немного калека и в основном желтый. Элемент __init__ функция вызывается конструктор или инициализатор, и автоматически вызывается при создании нового экземпляра класса. В рамках этой функции вновь созданный объект присваивается параметру self. Обозначение self.legs - это атрибут, называемый legs объекта в переменной self. Атрибуты похожи на переменные, но они опишите состояние объекта или конкретные действия (функции), доступные объекту.

однако обратите внимание, что вы не устанавливаете colour для самого догхантства-это абстрактное понятие. Есть атрибуты, которые имеют смысл в классах. Например, population_size является одним из таких - это не имеет смысла считать Фидо, потому что Фидо всегда один. Есть смысл пересчитать собак. Допустим, в мире 200 миллионов собак. Это собственность класса собак. Фидо имеет ничего общего с цифрой 200 миллионов, как и спот. Это называется "атрибут класса", в отличие от" атрибутов экземпляра", которые colour или legs выше.

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

, цифры... это более интересные темы. Скажем, Целые Числа. Их много, гораздо больше, чем собак. Я знаю, что у Python уже есть целые числа, но давайте играть в dumb и "реализовывать" их снова (путем обмана и использования целых чисел Python).

Итак, целые числа-это класс. У них есть некоторые данные (значение), и некоторые поведения ("добавьте меня к этому другому номеру"). Давайте покажем это:

class MyInteger:
    def __init__(self, newvalue)
        # imagine self as an index card.
        # under the heading of "value", we will write
        # the contents of the variable newvalue.
        self.value = newvalue
    def add(self, other):
        # when an integer wants to add itself to another integer,
        # we'll take their values and add them together,
        # then make a new integer with the result value.
        return MyInteger(self.value + other.value)

three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8

это немного хрупко (мы предполагаем other будет MyInteger), но мы будем игнорировать сейчас. В реальном коде мы бы не стали; мы бы проверили его, чтобы убедиться, и, возможно, даже принудили его ("вы не целое число? ей-богу, у вас есть 10 наносекунд, чтобы стать одним! 9... 8....")

мы могли бы даже определить фракции. Фракции тоже умеют складывать сами.

class MyFraction:
    def __init__(self, newnumerator, newdenominator)
        self.numerator = newnumerator
        self.denominator = newdenominator
        # because every fraction is described by these two things
    def add(self, other):
        newdenominator = self.denominator * other.denominator
        newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
        return MyFraction(newnumerator, newdenominator)

есть еще больше дроби, чем целые числа (не совсем, но компьютеры этого не знают). Давайте сделаем два:

half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6

ты на самом деле ничего не объявлял. Атрибуты подобны новому виду переменной. Нормальные переменные имеют только одно значение. Допустим, вы пишете colour = "grey". Вы не можете иметь другую переменную с именем colour что это "fuchsia" - не в том же месте в коде.

массивы решают это в определенной степени. Если вы скажете colour = ["grey", "fuchsia"], вы сложили два цвета в переменную, но отличить их положение (0 или 1, в данном случае).

атрибуты-это переменные, привязанные к объекту. Как и с массивами, у нас может быть много colour переменные на разных собак. Итак,fido.colour одна переменная, но spot.colour это другое. Первый привязан к объекту внутри переменной fido; второй, spot. Теперь, когда вы звоните Dog(4, "brown") или three.add(five), всегда будет невидимый параметр, который будет присвоен висячий дополнительный в передней части списка параметров. Он условно называется self, и получит значение объекта перед точкой. Таким образом, внутри собаки __init__ (конструктор), self будет тем, чем окажется новая собака; внутри MyInteger ' s add,self будет привязан к объекту в переменной three. Таким образом,three.value будет та же переменная вне add, а self.value внутри add.

если я говорю the_mangy_one = fido, я начнет ссылаться на объект, известный как fido еще одним именем. С этого момента,fido.colour точно такая же переменная как the_mangy_one.colour.

Итак, вещи внутри __init__. Вы можете думать о них как о заметках в свидетельстве о рождении собаки. colour сама по себе является случайной величиной, может содержать что угодно. fido.colour или self.colour это как поле формы на идентификационном листе собаки; и __init__ это клерк заполняет его в первый раз.

любой яснее?

EDIT: расширение комментария ниже:

Вы имеете в виду список объекты, не так ли?

прежде всего,fido на самом деле не объект. Это переменная, которая в настоящее время содержит объект, так же, как когда вы говорите x = 5,x - переменная, содержащая в настоящее время число пять. Если вы позже передумаете, вы можете сделать fido = Cat(4, "pleasing") (пока вы создали класс Cat), и fido с этого момента будет "содержать" объект кошки. Если вы это сделаете fido = x, тогда он будет содержать число пять, а не животный объект вообще.

класс сам по себе не знает своих экземпляров, если вы специально не пишете код, чтобы отслеживать их. Например:

class Cat:
    census = [] #define census array

    def __init__(self, legs, colour):
        self.colour = colour
        self.legs = legs
        Cat.census.append(self)

здесь census является атрибутом уровня класса Cat класса.

fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that

обратите внимание, что вы не получите [fluffy, sparky]. Это просто имена переменных. Если вы хотите, чтобы кошки сами имели имена, вы должны сделать отдельный атрибут для имени, а затем переопределить __str__ метод для возврата этого имени. Этот метод (т. е. функция с привязкой к классу, как и add или __init__) цель состоит в том, чтобы описать, как преобразовать объект в строку, например, когда вы его распечатываете.

внести свои 5 центов в подробное объяснение от Amadan.

где классы-это описание" типа " абстрактным образом. Объекты - это их реализации: живое дышащее существо. В объектно-ориентированном мире есть принципиальные идеи, которые можно почти назвать сущностью всего. Они таковы:

  1. инкапсуляция (не будем уточнять это)
  2. наследование
  3. полиморфизм

объекты имеют одну или несколько характеристик (= атрибуты) и поведение (= методы). Поведение в основном зависит от характеристик. Классы определяют, что поведение должно выполнять в общем виде, но до тех пор, пока класс не будет реализован (создан) как объект, он остается абстрактным понятием возможности. Позвольте мне проиллюстрировать с помощью "наследования" и "полиморфизм."

    class Human:
        gender
        nationality
        favorite_drink
        core_characteristic
        favorite_beverage
        name
        age

        def love    
        def drink
        def laugh
        def do_your_special_thing                

    class Americans(Humans)
        def drink(beverage):
            if beverage != favorite_drink: print "You call that a drink?"
            else: print "Great!" 

    class French(Humans)
        def drink(beverage, cheese):
            if beverage == favourite_drink and cheese == None: print "No cheese?" 
            elif beverage != favourite_drink and cheese == None: print "Révolution!"

    class Brazilian(Humans)
        def do_your_special_thing
            win_every_football_world_cup()

    class Germans(Humans)
        def drink(beverage):
            if favorite_drink != beverage: print "I need more beer"
            else: print "Lecker!" 

    class HighSchoolStudent(Americans):
        def __init__(self, name, age):
             self.name = name
             self.age = age

jeff = HighSchoolStudent(name, age):
hans = Germans()
ronaldo = Brazilian()
amelie = French()

for friends in [jeff, hans, ronaldo]:
    friends.laugh()
    friends.drink("cola")
    friends.do_your_special_thing()

print amelie.love(jeff)
>>> True
print ronaldo.love(hans)
>>> False

некоторые характеристики определяют человека. Но каждая национальность отличается. Так что "национальные типы" - это своего рода люди с массовкой. "Американцы "-это тип "людей" и наследуют некоторые абстрактные характеристики и поведение от человеческого типа (базового класса) : это наследование. Таким образом, все люди могут смеяться и пить, поэтому все детские классы также могут! Наследование (2).

но потому что они все одного вида (тип / базовый класс: Люди) иногда вы можете обменять их: см. for-loop в конце. Но они будут выставлять индивидуальную характеристику, и это полиморфизм (3).

таким образом, у каждого человека есть любимый напиток, но каждая национальность склонна к особому виду напитка. Если вы подкласс национальности от типа людей вы можете перезаписать унаследованное поведение, как я продемонстрировал выше с drink() метод. Но это все еще на уровне класса, и из-за этого еще обобщение.

hans = German(favorite_drink = "Cola")

создает экземпляр класса German и я "изменил" характеристику по умолчанию в начале. (Но если вы позвоните Гансу.пейте ('молоко') он все равно напечатает "мне нужно больше пива" - очевидный баг ... или, может быть, это то, что я назвал бы особенностью, если бы я был сотрудником более крупной компании. ;-)! )

характеристика типа, например, немцы (hans) обычно определяются через конструктор (в python:__init__) в момент создания экземпляра. Это точка, где вы определяете класс, чтобы стать объектом. Можно сказать, вдохнуть жизнь в абстрактное понятие (класс), наполнив его индивидуальными характеристиками и став объектом.

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

для защиты характеристик каждого объекта вы инкапсулируете их-значит вы пытаетесь соединить поведение и характеристика и затрудняют манипулирование им извне объекта. Это инкапсуляция (1)

Это просто для инициализации переменных экземпляра.

например, создать crawler экземпляр с определенным именем базы данных (из примера выше).

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

class Car:
    def __init__(self, color, brand, number_of_seats):
        self.color = color
        self.brand = brand
        self.number_of_seats = number_of_seats
        self.number_of_wheels = 4
        self.registration_number = GenerateRegistrationNumber()

так, в __init__ метод определения атрибутов экземпляра, который вы создаете. Итак, если мы хотим синий автомобиль Renault, для 2 человек, мы бы инициализировали или экземпляр Car например:

my_car = Car('blue', 'Renault', 2)

таким образом, мы создаем экземпляр Car класса. Элемент __init__ это тот, который обрабатывает наши конкретные атрибуты (например,color или brand) и его генерации других атрибутов, как registration_number.

классы-это объекты с атрибутами (состояние, характеристика) и методами (функции, емкости), которые специфичны для этого объекта (например, белый цвет и сила полета, соответственно, для утки).

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

в принципе __init__ устанавливает характеристики экземпляра автоматически, когда вы звоните instance = MyClass(some_individual_traits).

The __init__ функция настраивает все переменные-члены в классе. Поэтому, как только ваш bicluster будет создан, вы можете получить доступ к члену и получить значение обратно:

mycluster = bicluster(...actual values go here...)
mycluster.left # returns the value passed in as 'left'

Проверьте Python Docs для некоторых информация. Вы захотите взять книгу о концепциях OO, чтобы продолжить обучение.

похоже, вам нужно использовать __init__ в Python, если вы хотите правильно инициализировать изменяемых атрибутов экземпляров.

рассмотрим следующий пример:

>>> class EvilTest(object):
...     attr = []
... 
>>> evil_test1 = EvilTest()
>>> evil_test2 = EvilTest()
>>> evil_test1.attr.append('strange')
>>> 
>>> print "This is evil:", evil_test1.attr, evil_test2.attr
This is evil: ['strange'] ['strange']
>>> 
>>> 
>>> class GoodTest(object):
...     def __init__(self):
...         self.attr = []
... 
>>> good_test1 = GoodTest()
>>> good_test2 = GoodTest()
>>> good_test1.attr.append('strange')
>>> 
>>> print "This is good:", good_test1.attr, good_test2.attr
This is good: ['strange'] []

это совсем другое в Java, где каждый атрибут автоматически инициализируется с новым значением:

import java.util.ArrayList;
import java.lang.String;

class SimpleTest
{
    public ArrayList<String> attr = new ArrayList<String>();
}

class Main
{
    public static void main(String [] args)
    {
        SimpleTest t1 = new SimpleTest();
        SimpleTest t2 = new SimpleTest();

        t1.attr.add("strange");

        System.out.println(t1.attr + " " + t2.attr);
    }
}

выдает результат, который мы интуитивно ожидаем:

[strange] []

но если вы объявляете attr как static, он будет действовать как Python:

[strange] [strange]
class Dog(object):

    # Class Object Attribute
    species = 'mammal'

    def __init__(self,breed,name):
        self.breed = breed
        self.name = name

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

class Dog(object):
    a = '12'

    def __init__(self,breed,name,a):
        self.breed = breed
        self.name = name
        self.a= a

если вы напечатаете приведенный выше пример, позвонив ниже, как это

Dog.a
12

Dog('Lab','Sam','10')
Dog.a
10

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

Comments

    Ничего не найдено.