Почему мы используем 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__ я сталкиваюсь при попытке прочитать код других людей, но я не понимаю логики в их создании.
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' sadd,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.
где классы-это описание" типа " абстрактным образом. Объекты - это их реализации: живое дышащее существо. В объектно-ориентированном мире есть принципиальные идеи, которые можно почти назвать сущностью всего. Они таковы:
- инкапсуляция (не будем уточнять это)
- наследование
- полиморфизм
объекты имеют одну или несколько характеристик (= атрибуты) и поведение (= методы). Поведение в основном зависит от характеристик. Классы определяют, что поведение должно выполнять в общем виде, но до тех пор, пока класс не будет реализован (создан) как объект, он остается абстрактным понятием возможности. Позвольте мне проиллюстрировать с помощью "наследования" и "полиморфизм."
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.
- подробнее о классы в Python
- подробнее о
__init__метод
классы-это объекты с атрибутами (состояние, характеристика) и методами (функции, емкости), которые специфичны для этого объекта (например, белый цвет и сила полета, соответственно, для утки).
когда вы создаете экземпляр класса, вы можете дать ему первоначальные личности (государства или символ как имя и цвет ее платья для новорожденных). Вы делаете это с
__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