J'ai du mal à comprendre l'initialisation des classes.
À quoi servent-ils et comment savons-nous ce qu'il faut y inclure? Est-ce que l'écriture en classe nécessite un type de pensée différent de la création de fonctions (j'ai pensé que je pouvais simplement créer des fonctions, puis les envelopper dans une classe afin que je puisse les réutiliser. Cela fonctionnera-t-il?)
Voici un exemple:
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()
Ou un autre exemple de code:
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
Il y a tellement de classes avec __init__
que je rencontre en essayant de lire le code d'autres personnes, mais je ne comprends pas la logique de leur création.
D'après ce que vous avez écrit, il vous manque un élément essentiel de compréhension: la différence entre une classe et un objet. __init__
n'initialise pas une classe, il initialise une instance d'une classe ou d'un objet. Chaque chien a une couleur, mais les chiens en tant que classe n'en ont pas. Chaque chien a quatre pieds ou moins, mais pas la classe de chiens. La classe est un concept d'objet. Lorsque vous voyez Fido et Spot, vous reconnaissez leur ressemblance, leur doghood. C'est la classe.
Quand tu dis
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
Vous dites que Fido est un chien brun à 4 pattes alors que Spot est un peu infirme et qu’il est principalement jaune. La fonction __init__
s'appelle un constructeur, ou un initialiseur, et est appelée automatiquement lorsque vous créez une nouvelle instance d'une classe. Dans cette fonction, l’objet nouvellement créé est affecté au paramètre self
. La notation self.legs
est un attribut appelé legs
de l'objet dans la variable self
. Les attributs sont un peu les mêmes que les variables, mais ils décrivent l'état d'un objet ou des actions (fonctions) particulières disponibles pour cet objet.
Cependant, notez que vous ne définissez pas colour
pour le doghood lui-même - c'est un concept abstrait. Il y a des attributs qui ont du sens sur les classes. Par exemple, population_size
en est un. Cela n'a pas de sens de compter le Fido, car Fido en est toujours un. Il est logique de compter les chiens. Disons qu'il y a 200 millions de chiens dans le monde. C'est la propriété de la classe Dog. Fido n'a rien à voir avec le chiffre 200 millions, pas plus que Spot. C'est ce qu'on appelle un "attribut de classe", par opposition aux "attributs d'instance" qui sont colour
ou legs
ci-dessus.
Passons maintenant à quelque chose de moins canin et plus lié à la programmation. Comme je l'écris ci-dessous, ajouter un cours en classe n'est pas judicieux - de quoi s'agit-il? Les classes dans Python constituent des collections de données différentes, qui se comportent de la même manière. La classe de chiens est composée de Fido et Spot et 199999999998 autres animaux semblables à eux, tous pissant sur des lampadaires. En quoi consiste la classe pour ajouter des choses? Par quelles données inhérentes diffèrent-ils? Et quelles actions partagent-ils?
Cependant, les chiffres ... ce sont des sujets plus intéressants. Dis, entiers. Il y en a beaucoup, beaucoup plus que des chiens. Je sais que Python a déjà des entiers, mais jouons à la stupide et "implémentons-les" à nouveau (en trichant et en utilisant les entiers de Python).
Donc, les entiers sont une classe. Ils ont des données (valeur) et des comportements ("ajoute-moi à cet autre nombre"). Montrons ceci:
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
Ceci est un peu fragile (nous supposons que other
sera un MyInteger), mais nous l'ignorerons maintenant. En code réel, nous ne le ferions pas; nous le testerions pour nous en assurer, et peut-être même le forcerions-nous ("vous n'êtes pas un entier? par zut, vous avez 10 nanosecondes pour le devenir! 9 ... 8 ....")
Nous pourrions même définir des fractions. Les fractions savent aussi comment s'ajouter.
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)
Il y a même plus de fractions que de nombres entiers (pas vraiment, mais les ordinateurs ne le savent pas). Faisons deux:
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
En fait, vous ne déclarez rien ici. Les attributs sont comme un nouveau type de variable. Les variables normales ont une seule valeur. Disons que vous écrivez colour = "grey"
. Vous ne pouvez pas avoir une autre variable nommée colour
qui est "Fuchsia"
- pas au même endroit dans le code.
Les tableaux résolvent cela dans une certaine mesure. Si vous dites colour = ["grey", "Fuchsia"]
, vous avez empilé deux couleurs dans la variable, mais vous les distinguez par leur position (0 ou 1, dans ce cas).
Les attributs sont des variables liées à un objet. Comme avec les tableaux, nous pouvons avoir beaucoup de variables colour
, sur différents chiens . Donc, fido.colour
est une variable, mais spot.colour
en est une autre. Le premier est lié à l'objet dans la variable fido
; le second, spot
. Désormais, lorsque vous appelez Dog(4, "brown")
ou three.add(five)
, il y aura toujours un paramètre invisible, qui sera attribué au paramètre supplémentaire pendant au début de la liste des paramètres. Il est conventionnellement appelé self
, et obtiendra la valeur de l'objet devant le point. Ainsi, dans le __init__
(constructeur) du chien, self
sera ce que le nouveau chien se révélera être; dans MyInteger
'add
, self
sera lié à l'objet dans la variable three
. Ainsi, three.value
sera la même variable en dehors de add
, comme self.value
à l'intérieur de add
.
Si je dis the_mangy_one = fido
, je commencerai par faire référence à l'objet appelé fido
avec encore un autre nom. À partir de maintenant, fido.colour
est exactement la même variable que the_mangy_one.colour
.
Donc, les choses à l'intérieur du __init__
. Vous pouvez penser à eux en notant des choses dans l'acte de naissance du chien. colour
est en soi une variable aléatoire, peut contenir n'importe quoi. fido.colour
ou self.colour
est comme un champ de formulaire sur la fiche d'identité du chien; et __init__
est l’employé qui le remplit pour la première fois.
Plus clair?
EDIT: Développer le commentaire ci-dessous:
Vous voulez dire une liste de objets, n'est-ce pas?
Tout d'abord, fido
n'est en réalité pas un objet. C'est une variable qui contient actuellement un objet, comme lorsque vous dites x = 5
, x
est une variable contenant actuellement le nombre cinq. Si vous changez d'avis par la suite, vous pouvez utiliser fido = Cat(4, "pleasing")
(tant que vous avez créé une classe Cat
), et fido
"contiendra" par la suite un objet cat. Si vous faites fido = x
, il contiendra alors le nombre cinq et pas un objet animal du tout.
Une classe en elle-même ne connaît pas ses instances sauf si vous écrivez spécifiquement du code pour en garder la trace. Par exemple:
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
Ici, census
est un attribut au niveau classe de Cat
class.
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
Notez que vous n'obtiendrez pas [fluffy, sparky]
. Ce ne sont que des noms de variables. Si vous voulez que les chats eux-mêmes aient des noms, vous devez créer un attribut distinct pour le nom, puis substituer la méthode __str__
pour renvoyer ce nom. Le but de cette méthode (c'est-à-dire une fonction liée à la classe, tout comme add
ou __init__
) est de décrire comment convertir l'objet en chaîne, comme lorsque vous l'imprimez.
Pour contribuer mes 5 cents au explication approfondie d’Amadan .
Où classes sont une description "d'un type" de manière abstraite. Les objets sont leurs réalisations: la chose vivante qui respire. Dans le monde orienté objet, il y a des idées principales que vous pouvez presque appeler l'essence de tout. Elles sont:
Les objets ont une ou plusieurs caractéristiques (= attributs) et comportements (= méthodes). Le comportement dépend principalement des caractéristiques. Les classes définissent ce que le comportement doit accomplir de manière générale, mais tant que la classe n'est pas réalisée (instanciée) en tant qu'objet, elle reste un concept abstrait de possibilité. Permettez-moi d'illustrer à l'aide de "héritage" et "polymorphisme".
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
Certaines caractéristiques définissent les êtres humains. Mais chaque nationalité diffère quelque peu. Donc, les "types nationaux" sont un peu des humains avec des figurants. Les "Américains" sont un type d '"Humains" et héritent de caractéristiques humaines et de comportements abstraits du type humain (classe de base): c'est l'héritage. Ainsi, tous les humains peuvent rire et boire, donc toutes les classes d'enfants peuvent aussi! Héritage (2).
Mais comme ils sont tous du même genre (Type/base-class: Humans), vous pouvez les échanger parfois: voir la boucle for à la fin. Mais ils vont exposer une caractéristique individuelle, et c'est le polymorphisme (3).
Ainsi, chaque humain a son boisson favorite, mais chaque nationalité tend vers un type de boisson spécial. Si vous sous-classez une nationalité du type Humans, vous pouvez écraser le comportement hérité, comme je l'ai démontré ci-dessus avec la méthode drink()
. Mais cela reste au niveau de la classe et à cause de cela, cela reste une généralisation.
hans = German(favorite_drink = "Cola")
instancie la classe German et j'ai "changé" une caractéristique par défaut au début. (Mais si vous appelez hans.drink ("Lait"), il continuerait à écrire "J'ai besoin de plus de bière" - un bogue évident ... ou peut-être que ce serait ce que j'appellerais une fonctionnalité si je serais un employé d'une plus grande entreprise. ;-)! )
La caractéristique d'un type, par exemple Les Allemands (hans) sont généralement définis par le constructeur (en python: __init__
) au moment de l'instanciation. C'est le point où vous définissez une classe pour qu'elle devienne un objet. Vous pouvez dire insuffler la vie dans un concept abstrait (classe) en le remplissant de caractéristiques individuelles et en devenant un objet.
Mais comme chaque objet est une instance d'une classe, ils partagent tous certains types de caractéristiques de base et certains comportements. C'est un avantage majeur du concept orienté objet.
Pour protéger les caractéristiques de chaque objet que vous les encapsulez, cela signifie que vous essayez de coupler comportement et caractéristique et vous empêchez de le manipuler de l'extérieur. C'est l'encapsulation (1)
Il suffit d'initialiser les variables de l'instance.
Par exemple. créez une instance crawler
avec un nom de base de données spécifique (d'après votre exemple ci-dessus).
Il semble que vous ayez besoin d'utiliser __init__
dans Python si vous souhaitez initialiser correctement les attributs modifiables de vos instances.
Voir l'exemple suivant:
>>> 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'] []
Ceci est assez différent dans Java où chaque attribut est automatiquement initialisé avec une nouvelle valeur:
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);
}
}
produit une sortie que nous attendons intuitivement:
[strange] []
Mais si vous déclarez attr
comme static
, il agira comme Python:
[strange] [strange]
Après avec votre voiture exemple: quand vous obtenez une voiture, vous n’obtenez pas une voiture au hasard, je veux dire, vous choisissez la couleur, la marque , nombre de places, etc. Et certaines choses sont aussi "initialiser" sans que vous le choisissiez, comme le nombre de roues ou le numéro d’immatriculation.
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()
Ainsi, dans la méthode __init__
, vous définissez les attributs de l'instance que vous créez. Donc, si nous voulons une voiture Renault bleue, pour 2 personnes, nous initialiserions une instance de Car
comme:
my_car = Car('blue', 'Renault', 2)
De cette façon, nous créons une instance de la classe Car
. Le __init__
est celui qui gère nos attributs spécifiques (comme color
ou brand
) et génère les autres attributs, comme registration_number
.
__init__
)Les classes sont des objets avec des attributs (état, caractéristiques) et des méthodes (fonctions, capacités) spécifiques à cet objet (comme la couleur blanche et les pouvoirs de vol, respectivement, pour un canard).
Lorsque vous créez une instance d'une classe, vous pouvez lui attribuer une personnalité initiale (état ou caractère tel que le nom et la couleur de sa robe pour un nouveau-né). Vous faites cela avec __init__
.
__init__
définit les caractéristiques de l'instance automatiquement lorsque vous appelez instance = MyClass(some_individual_traits)
.
La fonction __init__
configure toutes les variables membres de la classe. Ainsi, une fois votre bicluster créé, vous pouvez accéder au membre et obtenir une valeur:
mycluster = bicluster(...actual values go here...)
mycluster.left # returns the value passed in as 'left'
Consultez le Python Docs pour plus d’informations. Vous aurez envie de prendre un livre sur OO concepts pour continuer à apprendre.
class Dog(object):
# Class Object Attribute
species = 'mammal'
def __init__(self,breed,name):
self.breed = breed
self.name = name
Dans l'exemple ci-dessus, nous utilisons les espèces comme globales, car elles seront toujours les mêmes (type de constante que vous pouvez dire). Lorsque vous appelez la méthode __init__
, alors toute la variable à l'intérieur de __init__
sera lancée (par exemple: breed, name).
class Dog(object):
a = '12'
def __init__(self,breed,name,a):
self.breed = breed
self.name = name
self.a= a
si vous imprimez l'exemple ci-dessus en appelant ci-dessous comme ceci
Dog.a
12
Dog('Lab','Sam','10')
Dog.a
10
Cela signifie qu'il ne sera initialisé que lors de la création de l'objet. de sorte que tout ce que vous voulez déclarer constant soit global et tout ce qui change utilise __init__