Python, tworzenie obiektów

137

Próbuję nauczyć się Pythona, a teraz próbuję opanować klasy i manipulować nimi za pomocą instancji.

Wydaje się, że nie rozumiem tego problemu:

Utwórz i zwróć obiekt studenta, którego imię i nazwisko, wiek i kierunek są takie same jak te podane jako dane wejściowe

def make_student(name, age, major)

Po prostu nie rozumiem, co to oznacza przez obiekt, czy oznaczają one, że powinienem utworzyć tablicę wewnątrz funkcji, która przechowuje te wartości? czy utworzyć klasę i pozwolić tej funkcji być wewnątrz niej i przypisać instancje? (przed tym pytaniem poproszono mnie o utworzenie klasy studenckiej z podaniem imienia i nazwiska, wieku i specjalności)

class Student:
    name = "Unknown name"
    age = 0
    major = "Unknown major"
Mohsen M. Alrasheed
źródło
Przeczytaj dokumentację dotyczącą modelu danych, w szczególności __init__metoda jest odpowiednia tutaj: docs.python.org/2/reference/datamodel.html#object.__init__
wim,
1
Brak (bez cudzysłowów) jest powszechną nieprzypisaną wartością domyślną w Pythonie
monkut

Odpowiedzi:

177
class Student(object):
    name = ""
    age = 0
    major = ""

    # The class "constructor" - It's actually an initializer 
    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major

def make_student(name, age, major):
    student = Student(name, age, major)
    return student

Zauważ, że chociaż jedną z zasad filozofii Pythona jest „powinien istnieć jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego” , wciąż istnieje wiele sposobów, aby to zrobić. Możesz także użyć dwóch poniższych fragmentów kodu, aby skorzystać z dynamicznych możliwości Pythona:

class Student(object):
    name = ""
    age = 0
    major = ""

def make_student(name, age, major):
    student = Student()
    student.name = name
    student.age = age
    student.major = major
    # Note: I didn't need to create a variable in the class definition before doing this.
    student.gpa = float(4.0)
    return student

Wolę tę pierwszą, ale są przypadki, w których ta druga może być przydatna - na przykład podczas pracy z bazami danych dokumentów, takimi jak MongoDB.

Wulfram
źródło
17
dlaczego inicjalizujesz je jako zmienne klasowe przed swoim initem? (ciekawe; nie widziałem tego wzoru zbyt często)
GoingTharn
7
Ze względu na czytelność. Umieszczając zmienne klasy u góry przed initem, mogę szybko zobaczyć, które zmienne znajdują się w zakresie klasy, ponieważ nie wszystkie mogą zostać ustawione przez konstruktora.
Wulfram
1
Tutaj nazwa obiektu będącego instancją klasy Uczeń pozostanie studentem, prawda? Co się stanie, jeśli w każdym wywołaniu chcę mieć wiele obiektów o nazwach student01, student02 itd.?
Yathi
9
Tworzenie zmiennych klas, aby zobaczyć, jakie zmienne instancji są okropną praktyką. Do wszystkich początkujących czytelników: zamiast tego spójrz na odpowiedź @ pyrospade.
anon01
2
Twój przykład jest mylący. Prosimy o używanie nazw zmiennych klas, które w rzeczywistości są własnością wszystkich uczniów, a nie nadużywanie własności każdego ucznia. Na przykład: użyj class Unicorni has_hooves = Truezamiast name = "".
Tim Kuipers
52

Utwórz klasę i nadaj jej __init__metodę:

class Student:
    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major

    def is_old(self):
        return self.age > 100

Teraz możesz zainicjować instancję Studentklasy:

>>> s = Student('John', 88, None)
>>> s.name
    'John'
>>> s.age
    88

Chociaż nie jestem pewien, dlaczego potrzebujesz make_studentfunkcji studenta, jeśli robi to samo, co Student.__init__.

Mikser
źródło
Nasz nauczyciel dał nam program test.py, który sprawdza, czy rozwiązaliśmy problemy poprawnie. Pytanie chce, żebym specjalnie użył funkcji make_student. Ostatecznym celem jest: s1 = make_student (imię, wiek, kierunek) i teraz mam wszystko przypisane do s1. Ale znowu nie jestem pewien, kim chcą, żeby s1 było? Mogę to zrobić z tablicą {'name': name..etc}, ale to nie dało mi poprawnej odpowiedzi, więc zakładam, że muszę zaimplementować to, czego nauczyłem się z klas i instancji
Mohsen M. Alrasheed
1
Tak zwany wzorzec "metody fabrycznej", czyli ten, w którym używasz metody lub funkcji do stworzenia jakiegoś obiektu zamiast tworzenia ich bezpośrednio w kodzie, jest użytecznym wzorcem, pozwala na przykład wykorzystać fajne rzeczy związane z dziedziczeniem . Spójrz;)
bracco23
28

Obiekty są instancjami klas. Klasy to tylko plany obiektów. Biorąc więc pod uwagę definicję klasy -

# Note the added (object) - this is the preferred way of creating new classes
class Student(object):
    name = "Unknown name"
    age = 0
    major = "Unknown major"

Możesz utworzyć make_studentfunkcję, jawnie przypisując atrybuty do nowej instancji Student-

def make_student(name, age, major):
    student = Student()
    student.name = name
    student.age = age
    student.major = major
    return student

Ale prawdopodobnie bardziej sensowne jest zrobienie tego w konstruktorze ( __init__) -

class Student(object):
    def __init__(self, name="Unknown name", age=0, major="Unknown major"):
        self.name = name
        self.age = age
        self.major = major

Konstruktor jest wywoływany, gdy używasz Student(). Pobierze argumenty zdefiniowane w __init__metodzie. Teraz w zasadzie sygnatura konstruktora będzie Student(name, age, major).

Jeśli tego użyjesz, make_studentfunkcja jest trywialna (i zbyteczna) -

def make_student(name, age, major):
    return Student(name, age, major)

Dla zabawy, oto przykład tworzenia make_studentfunkcji bez definiowania klasy. Nie próbuj tego w domu.

def make_student(name, age, major):
    return type('Student', (object,),
                {'name': name, 'age': age, 'major': major})()
pirospada
źródło
Właściwie wolę nie robić klasy Nazwa (obiekt): ze względu na szczegółowość. Dokumentacja Pythona raczej tego nie robi. Podoba mi się jednak „niebezpieczny” przykład karmienia dyktando. docs.python.org/2/tutorial/classes.html
Wulfram
1
Wycofuję swój poprzedni komentarz. Zobacz stackoverflow.com/questions/4015417/… . Jest więc właściwie powód, aby przeliterować nazwę klasy (obiekt):
Wulfram,
1
W Pythonie nie ma konstruktora :)
BigSack
Czym __init__()różni się ta metoda od konstruktora?
pirospada
1
__init__nie jest konstruktorem, "ponieważ obiekt został już skonstruowany przed __init__wywołaniem, a masz już poprawne odniesienie do nowej instancji klasy." ( diveintopython.net/object_oriented_framework/… )
Brian Z
3

kiedy tworzysz obiekt przy użyciu predefiniowanej klasy, najpierw chcesz utworzyć zmienną do przechowywania tego obiektu. Następnie możesz utworzyć obiekt i przechowywać zmienną, którą utworzyłeś.

class Student:
     def __init__(self):

# creating an object....

   student1=Student()

W rzeczywistości ta metoda init jest konstruktorem klasy. Możesz zainicjować tę metodę przy użyciu niektórych atrybutów .. W tym momencie, podczas tworzenia obiektu, będziesz musiał przekazać pewne wartości dla poszczególnych atrybutów.

class Student:
      def __init__(self,name,age):
            self.name=value
            self.age=value

 # creating an object.......

     student2=Student("smith",25)
GT_hash
źródło