#python #python-3.x #class
#python #python-3.x #класс
Вопрос:
я изучаю объектно-ориентированное программирование на Python и пытаюсь написать программу, которая вызывает класс B в качестве переменной для класса A. Могу ли я узнать, правильный ли мой подход к обработке этого?
Пример класса A
Class A():
_name = str
_cost = int
def __init__(self, _name, _cost):
self.name = _name
self.cost = _cost
def name(self):
return self.name
def cost(self):
return self.cost
Пример класса B
Class B():
_a = A
def __init__(self,_a):
self.a = _a
def __str__(self):
return 'Phone Model: ', a.name, 'Cost: ', a.cost
phone= B('phone_X', 100)
print(phone.__str__())
Заранее благодарю вас!
Комментарии:
1.Что вы здесь делаете:
_name = str
? Почему вы создаете эти переменные класса (т. Е. статические)? Вы пришли с такого языка, как Java / C #? Ваш подход неверен. Например, в__str__
a
не определено, вы имеете в видуself.a
, но почему, опять же, вы делаете_a = A
в классеB
в качестве переменной класса? Вы никогда его не используете.2. Вы определяете,
B
чтобы принимать один аргумент, но затем вы пытаетесь создать его какB('phone_X', 100)
, так что это не удастся.3. кстати, элементы вне метода init являются статическими элементами; они принадлежат классу. Элементы внутри метода init являются элементами объекта (self);
4. Обратите внимание, что
dataclasses
модуль использует синтаксис, очень похожий на то, что в настоящее время имеет OP для автоматической генерации различных методов (например__init__
).5. Сначала я хотел инициализировать переменную с определенным типом, но, похоже, это был неправильный подход, спасибо за разъяснение
Ответ №1:
Это должно сработать. Обратите внимание, что я упростил логику классов A и B.
class A():
# name and cost are constructor arguments
def __init__(self, name, cost):
self.name = name
self.cost = cost
Мы удалили _name
и _cost
, потому что мы хотим присвоить значения name
и cost
, когда мы вызываем новый экземпляр класса A, что делается в __init__
. Итак, когда вы хотите создать экземпляр класса A, вы должны присвоить значения, подобные этому:
product = A("phoneX",5)
.
Теперь у вас есть экземпляр класса A под названием «product», который имеет name = "phoneX"
и cost = 5
.
class B():
# Passing object of A as an argument
def __init__(self, a):
self.a = a
# This function should return a string
def __str__(self):
return 'Phone Model: ' self.a.name ' Cost: ' str(self.a.cost)
# Instantiating object of A and passing it to B
a = A('phone_X', 100)
phone= B(a)
# Just printing the object would suffice
print(phone)
# Phone Model: phone_X Cost: 100
Мы удалили _a
по тем же причинам, по которым мы удалили переменные _name
и _cost
в классе A. В __init__
для этого класса вы предполагаете, что переменная ‘a’ будет экземпляром класса A. Таким образом, у нее будет переменная name
и cost
.
Комментарии:
1. Похоже, что OP намеревался
B
принятьA
объект в качестве аргумента.2. Обновлено соответствующим образом
3. Это было бы неуместно, но для OP было бы полезно, если бы вы объяснили OP, что их код делал правильно / неправильно и почему ваша версия является наилучшей практикой?
4. Я добавил комментарии к своему коду, чтобы сделать именно это. Не стесняйтесь изменять мой ответ @Rook, чтобы сделать то же самое, поскольку я также новичок в SO и не уверен, какие изменения будут полезны для OP
5. Только что отредактировал ваш пост. Я забыл объяснить операторы печати.
Ответ №2:
Те вещи, которые вы в настоящее время пытаетесь сделать в A
(объявить существование и тип каждой переменной экземпляра), — это то, что dataclasses
модуль поддерживает, начиная с Python 3.7.
from dataclasses import dataclass
@dataclass
class A():
name: str
cost: int
В Python нет необходимости определять метод, который ничего не делает, кроме как возвращает значение атрибута экземпляра; просто получите доступ к атрибуту напрямую.
@dataclass
class B():
_a: A
def __str__(self):
return f'Phone Model: {self._a.name}, Cost: {self._a.cost}'
Теперь вы можете передать явно определенный экземпляр A
в качестве аргумента B
, затем передать экземпляр B
в str
, чтобы получить строковое значение.
phone = B(A('phone_X', 100))
print(str(phone))
Комментарии:
1. Это очень круто и выполняет более чистую работу, чем другой ответ. Однако OP является новым для Python и объектно-ориентированного программирования, поэтому использование декораторов может помешать OP понять стиль программирования, который они изучают. Отличное знакомство с нюансами Python.
2. спасибо за совет, я рассмотрю использование dataclass
3. Либо
return 'Phone Model: {}, Cost: {}'.format(self._a.name, self._a.cost)
, либоreturn f'Phone Model: {self._a.name}, Cost: {self._a.cost}')
. 2-й вариант более элегантный, имхо, и, учитывая, что вы предлагаете классы данных, тогда f-строки отлично поддерживаются4. Согласен; большая часть кода, над которым я работаю, все еще находится в процессе перехода с Python 2 на Python 3, поэтому f-строки еще не первое, о чем я думаю для форматирования строк.