использование собственного аргумента - PullRequest
2 голосов
/ 28 декабря 2011

Я новичок в Python. Я не понимаю, как / почему используется аргумент self:

class Person:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print 'Hello, my name is', self.name

p = Person('Swaroop')
p.sayHi()

Этот код взят из байта Python. Этот код мог быть так же легко написан как:

def sayHi(self, name):
            print 'Hello, my name is', name

p = Person('Swaroop')
p.sayHi()

... не так ли? Какова цель сделать name полем self?

Ответы [ 5 ]

6 голосов
/ 28 декабря 2011

Кажется, вы упрощаете не очень простую вещь. В объектно-ориентированном программировании класс представляет собой декларативную конструкцию, которая дает представление о том, что объект (проявление этого проекта) будет содержать (свойства) и как он будет вести себя (члены). Каждое проявление такого Класса называется Объектом, который имеет определенный и конкретный экземпляр. От объекта через любой из этих поведенческих атрибутов, называемых функциями / методами-членами, нам нужно как-то сослаться на этот экземпляр объекта и запомнить отдельные элементы внутри него и провести четкое различие с другими объектами, не являющимися членами.

Рассмотрим Ваш пример

class Person:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print 'Hello, my name is', self.name

Каждый экземпляр этого персонажа (Том, ​​Дик, Гарри) уникален, и в каждом экземпляре для обращения к самому себе нам нужна некоторая идиома, например (self в Python, это ptr C ++ или это в Java).

Таким образом, в методе __init__, когда вам нужно разграничить атрибут name объекта Person с параметром name, мы легко можем сделать это с помощью self. Мало того, что в любом случае мы можем продолжать ссылаться на это имя через self.

Создание экземпляра Person p=Person('Swaroop') с последующим вызовом sayHi в отличие от вызова просто функции sayHi, которая не является частью объекта, имеет два значения

  1. Функция временная, не имеет состояния, никакого экземпляра, и это как сказать этому парню: «Эй, мистер, кто бы вы ни говорили,« Здравствуйте, меня зовут Swaroop »». Это как при каждом пробежке вы должны заставить дурака узнать его имя, который забудет в следующий момент, когда вы встретите его. Как будто этот парень страдает от Anterograde_amnesia . С другой стороны, вызов sayHi экземпляра Person по имени Swaroop будет означать что-то вроде физически существующего Swaroop, приветствующего его Имя, которое имеет постоянную память и никогда не забудет, если не примет новое имя.
  2. Функция никогда не запоминает, а забывает каждый раз, когда заканчивается вызов. Объект Person будет помнить имя до тех пор, пока вы явно или неявно не убьете этого человека.

Если у вас есть опыт работы с C ++ и вам может быть интересно, зачем вообще нужно добавлять этот дополнительный параметр в вызов функции, где, как и в C ++, этот указатель никогда не передается. Ну, откровенно говоря, это так. Если вы читаете соглашение о вызовах C ++, будь то X86 или X64, указатель this передается в регистр ecx методу, чтобы получить дескриптор самого себя. Это более очевидно здесь, где мы сознательно передаем дескриптор текущего экземпляра методу.

4 голосов
/ 28 декабря 2011

Взгляните на новый метод sayHiTo:

class Person:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print 'Hello, my name is', self.name
    def sayHiTo(self, other):
        print 'Hello', other.name, ' my name is', self.name

p1 = Person('Swaroop')
p2 = Person('codeninja')
p1.sayHiTo(p2)
p2.sayHiTo(p1)
2 голосов
/ 28 декабря 2011

На самом деле нет.Ваш второй пример не верен.Ключевое слово «self» - это специальная ссылка, которая передается методам экземпляра класса.Он представляет фактический экземпляр класса в этой области.Когда вы делаете класс, это просто общее определение.Затем вы создаете экземпляры этого класса.Каждый экземпляр уникален, и поэтому методы должны иметь возможность работать с этим экземпляром.У вас нет возможности узнать их, пока они не сделаны, поэтому «я» передает их вам.

Например, если вы создали два экземпляра своего класса личности:

p1 = Person("john")
p2 = Person("sam")

selfЗначение .name отличается для каждого из них.И когда вы вызываете sayHi () для каждого экземпляра:

p1.sayHi()
> Hello, my name is john
p2. sayHi()
> Hello, my name is sam

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

def sayHi(name):
        print 'Hello, my name is', name

    p = Person('Swaroop')
    p.sayHi()

> sayHi("john")

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

0 голосов
/ 28 декабря 2011

Вы не можете сравнить функцию в классе только с функцией. Конечно, вы можете передать имя, но идея использования класса заключается в том, что вы инкапсулируете данные. Наличие vars, связанного с self, означает, что вы можете обойти объект, и этот объект всегда может иметь доступ к своим «переменным-членам». Какой-то другой класс может использовать экземпляр Person, и ему не нужно знать имя этого человека, чтобы сказать привет.

0 голосов
/ 28 декабря 2011

Целью является сохранение ссылки на имя, чтобы вы могли ссылаться на нее в другом методе класса, например def sayHi (self)

...