Test mit PyCharm

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Ich hab vor vielen Jahren in meiner Freizeit einiges programmiert (Netrexx), und versuche gerade meine ersten Schritte in Python.

Also, Python ist installiert, und ich hab mir PyCharm heruntergeladen, Tutorial durchgelesen, und jetzt steh ich einmal kurz an.

Vom Tutorial hab ich als Test die "class Dog" heruntergeladen, und als Python Datei abgespeichert (https://docs.python.org/3/tutorial/classes.html). Was ich jetzt gerne probieren wuerde ist, diese Klasse zu importieren, und einige instanzen der Klasse generieren, und testen.

Der import funktioniert, die instanzierung der Klasse allerdings nicht mehr.

>>>d = Dog('Fido')

Das Problem ist, dass ich in PyCharm in der Konsole eine Fehlermeldung bekomme.

Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'module' object is not callable

Irgendwelche Tips?
nezzcarth
User
Beiträge: 1778
Registriert: Samstag 16. April 2011, 12:47

Wenn das Modul, das du importierst "Dog" oder so heißt, musst du es mitteles "Dog.Dog(…)' instantiieren (es sei denn du hast, es per 'from Dog import Dog' oder 'from Dog import *' (nicht machen!) importiert). Das Schema ist in dem Fall '<modulname_ohne_Endung>.<Klasse>'.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Antrazith: Laut Fehlermeldung versuchst Du ein Module aufzurufen. Also vermute ich mal Du hast das Modul mit der `Dog`-Klasse darin auch `Dog` genannt und dann ``import Dog`` geschrieben. Das importiert das Modul und bindet es an den Namen `Dog`. Die Klasse ist *in* dem Modul und kann über den ``.``-Operator erreicht werden. Gib einfach mal nur ``Dog`` ein, und dann ``Dog.Dog`` und schau was Dir da ausgegeben wird in der Python-Shell. Wenn die Klasse an den Namen `Dog` gebunden werden soll, müsste der Import so aussehen: ``from Dog import Dog``.

Das Modul sollte übrigens nicht `Dog` heissen, denn Module benennt man `klein_mit_unterstrichen` wie fast alles andere. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Siehe auch den Style Guide for Python Code.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Bin mir nicht sicher, ob ich die Antworten richtig verstanden hab, deshalb poste ich kurz einmal den Quelltext von "Dog.py".

class Dog:

kind = 'canine' # class variable shared by all instances

def __init__(self, name):
self.name = name # instance variable unique to each instance
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Hier noch ein paar Zeilen Output von der Python Console

>>>import Dog
[...keine Fehlermeldung]

>>>Dog
<module 'Dog' from 'C:\\Users\\Andreas\\Google Drive\\Programmieren\\Python\\Koyaanisqatsi\\Dog.py'>

>>>myDog = Dog('Schaefer')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'module' object is not callable
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Antwort hat BlackJack doch schon gegeben:

Code: Alles auswählen

myDog = Dog.Dog('Schaefer')
Das Modul Dog sollte aber dog heißen und bei myDog, eigentlich my_dog ist das my-Prefix ziemlich nichtssagend, »schaefer« als Variablenname wäre da besser.
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Ok, das akzeptiere ich jetzt einmal widerspruchslos.

Allerdings verstehen tu ich es trotzdem nicht.

Hier der Originalcode von der Pyton-Homepage (https://docs.python.org/3/tutorial/classes.html, Punkt 9.3.5)
Die Instanzierung der Klasse erfolgt hier naemlich so wie von mir angegeben. Allerdings hab ich noch nicht ganz verstanden, ob das nur funktioniert, wenn der Kode in der selben Datei ist. Moeglicherweise funktionert das nicht, wenn die Klasse in einer Datei ist, und die Instanzierung auf der Konsole gemacht wird.

class Dog:

kind = 'canine' # class variable shared by all instances

def __init__(self, name):
self.name = name # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
nezzcarth
User
Beiträge: 1778
Registriert: Samstag 16. April 2011, 12:47

Der Punkt ist, wenn du die Klasse in eine '.py' Datei schreibst (die bei dir dann leider auch noch verwirrenderweise ebenfalls 'Dog(.py)' heißt) ist das in dem Zusammenhang ein bisschen etwas anderes, als wenn man -- wie in dem Tutorial -- die Klasse im interaktiven Interpreter definiert und instanziiert. Denn dann ist sie gleich im Namenraum. Damit das so wie im Tutorial funktioniert müsstest du 'from Dog import Dog' schreiben, da du die Klasse 'Dog' aus dem Modul 'Dog(.py)' haben möchtest. Python ist keine von den Programmiersprachen, wo man eine Klasse pro Datei hat. Eine '.py' Datei, d.h. ein Modul bildet einen eigenen Namespace der diverse Funktionen, Klassen etc. haben kann. Die kannst du dir entweder jeweils mit einem 'from Dog import Dog, Leash, …' reinholen, oder du importierst eben nur das Modul 'Dog' und musst dann jeweils schreiben 'Dog.Dog', 'Dog.Leash' etc. Wenn du die Datei nicht Dog.py nennst, wird es vielleicht ein bisschen leichter.
Zuletzt geändert von nezzcarth am Donnerstag 26. Juli 2018, 22:03, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Antrazith: Der Text geht davon aus das die Klasse entweder in der Shell definiert wurde oder eben importiert wurde. Du importierst das Modul und nicht die Klasse aus dem Modul. Das heisst, wie man an der Ausgabe ja auch schön sehen kann, ist `Dog` das Modul und `Dog.Dog` die Klasse `Dog` im Modul `Dog`.

Ich würde das Modul auch nicht `dog` nennen, denn dann könnte man wieder mit einem Namen `dog` für ein Exemplar von `Dog` durcheinander kommen, denn so ein `my*`-Präfix ist unschön. Manche nennen so ein Modul dann `doglib`, mit `lib` als Kurzform für `library`. Ich denke das Problem ist, das es ein viel zu triviales ”Spielzeugbeispiel” ist um da für alles sinnvolle Namen zu finden. :-)

Das `kind`-Attribut sollte dann übrigens gross geschrieben werden, denn es ist ja eine Konstante.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Das war jetzt sehr hilfreich, vielen Dank.

Der Schluesselsatz war "Python ist keine von den Programmiersprachen, wo man eine Klasse pro Datei hat.". Bei Netrexx war das naemlich so.
Ich hab jetzt einmal kurz die Datei auf "Tutorial.py" umbenannt, und sonst alles gleich gelassen.

Mit "from Tutorial import Dog" hat alles weitere dann naemlich geklappt.

Fuer die anderen kleinen Fehler werd ich sicher noch ein paar Wochen brauchen, bis ich mich da durchgebissen hab.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Antrazith: Wie gesagt: Modulnamen klein_mit_unterstrichen. :-)
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Antrazith
User
Beiträge: 13
Registriert: Donnerstag 26. Juli 2018, 16:39

Ok, werd ich mir merken.

Kurze Frage zum Abschluss.

Wieviele Dateien macht man normalerweise in einem Projekt, oder nach welchen Kriterien werden Module oder Klassen in einer Datei zusammengefasst?
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Antrazith: Die Kriterien sind: gehört das zusammen oder nicht. Falls ein Modul sehr lang wird, auch wenn die Dinge darin zusammen gehören, könnte man trotzdem über eine sinnvolle Aufteilung nachdenken. Bei so um die 1.000 Zeilen fange ich persönlich an mir Gedanken zu machen.

Wenn man aufteilt, sollte man gleich alles in ein Package stecken, damit auf ”oberster Ebene” nur ein Name existiert der mit anderen Modulen und Packages kollidieren kann.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Antworten