如何拆分()一个字符串并将其传递给一个对象的__init __()方法?

时间:2018-05-14 02:38:54

标签: python class split factory static-methods

我正在尝试使用文件中的信息创建Soda对象的多个实例。该文件的格式如下,名称,价格,数字

Mtn. Dew,1.00,10

Coke,1.50,8

Sprite,2.00,3

我的代码是这个(这是main()中的一个函数):

from Sodas import Soda

def fillMachine(filename) :

    # Create an empty list that will store pop machine data
    popMachine = []

    # Open the file specified by filename for reading
    infile = open(filename, "r")

    # Loop to read each line from the file and append a new Soda object 
    # based upon information from the line into the pop machine list.
    for line in infile :
        popMachine.append(Soda(str(line.strip())))

    # Close the file
    infile.close()

    # Return the pop machine list
    return popMachine

如果我说得对,popMachine应该是3个不同Soda对象的列表,每个对象都有一行输入文件。

在我的班级中,我需要能够获得稍后用于计算的名称,价格或数量。我的类Sodas代码如下所示:

#Constructor
def __init__(self, _name = "", _price = 0.0, _quantity = 0) :
        self._name = self.getName()
        self._price = _price
        self._quantity = _quantity

def getName(self) :
    tempList = self.split(",")
    self._name = tempList[0]
    return self._name

这是我遇到问题的地方。 IIRC self代替主代码中的行,所以self应该是一个字符串,例如" Mtn。露,1.00,10"并且分裂(",")方法的预期结果应该形成像[" Mtn。露"," 1.00"," 10"]然后,我可以使用该列表的索引返回名称。

但是,我收到此错误"属性错误:Soda实例没有属性' split'"而且我不确定为什么。此外,此代码中的所有注释都来自我的教师作为任务的一部分,所以即使有更快/更好的方法来完成这一切,这是我必须这样做的方式:/

5 个答案:

答案 0 :(得分:1)

self变量引用对象实例。你可以做的是 分割构造函数中的行,如此

def __init__(self, line):
    name, price, quantity = line.split(',')
    self.name = name
    self.price = price
    self.quantity = quantity

...或者你可以在被要求时懒得分开它

def __init__(self, line):
    self._name = None
    self.line = line

@property
def name(self):
    if self._name is None:
        self._name = self.line.split()[0]
    return self._name

请注意,在函数名称等python变量中,按惯例通常为snake_case

答案 1 :(得分:1)

当您使用self时,您会引用Soda的实例,并且由于您尚未定义拆分方法,因此它不会有一个。

您只需使用解包即可将split的结果传递给班级。

您可能希望添加一些检查以确保解包返回三个值,但是因为您使用默认参数,所以只有在提供 more 而不是三个值时才会出错。

class Soda:
  def __init__(self, name = "", price = 0.0, quantity = 0) :
        self.name = name
        self.price = price
        self.quantity = quantity


sodas = []
with open('test.txt') as f:
  for line in f:
    sodas.append(Soda(*line.split(',')))

for soda in sodas:
  print(soda.name)

输出:

Mtn. Dew
Coke
Sprite

您甚至可以定义一个帮助方法,该方法从文件中的一行返回Soda实例:

@staticmethod
def make_soda(line):
  try:
    name, price, quantity = line.split(',')
    return Soda(name, price, quantity)
  except:
    raise ValueError('Bad Soda')

您可以使用以下方式致电:

Soda.make_soda(line)

答案 2 :(得分:1)

  

IIRC self代替主代码中的行,所以自我应该是   一个字符串,如" Mtn。露,1.00,10"和预期的结果   split(",")方法应该形成一个像[" Mtn。露"," 1.00"," 10"]   然后,我可以使用该列表的索引返回名称。

坚持一分钟。当人们学习编码时,这是一种常见的误解。从根本上说,您将源代码与数据类型str混为一谈。这是一个容易犯的错误,实际上,当编写源代码时,会创建一个文本文件。一个人将文本写入文件,甚至可以在Python中加载open('my_script.py').read()),我们得到一个字符串!是的,当您的源代码从您的编程语言到达之旅时,您运行的程序会使用字符串。机器代码。但我提倡你把这两件事分开。你的源代码不是一个字符串。它应该在概念上位于"上面#(无论如何,我们在这里处理有用的抽象)。所以,虽然你的想法基本上是正确的,

  

self代替主代码中的行

但是这里"线"表示行引用的行,代码执行的逻辑片段,而不是您编写的代码行。因此,self在方法由类的实例执行时引用对象 instance

因此,self 不是字符串。它是您的类定义的类型的对象。你的班级没有这种方法。 str个对象可以。

在这里看一下python数据模型。 "自"非常直截了当。实例本身作为参数传递。这是通过" magic"为您完成的。 (你可以学习以后玩的魔法)但基本上,my_instance.some_method() 大致相当于MyClass.some_method(my_instance)

考虑一下,

In [1]: class SomeClass:
   ...:     def __init__(self, name):
   ...:         self.name = name
   ...:     def foo(self):
   ...:         print(self.name, 'says foo!')
   ...:

In [2]: some_instance = SomeClass('Juan')

In [3]: some_instance.foo()
Juan says foo!

In [4]: SomeClass.foo(some_instance)
Juan says foo!

方法只是一个属于类的一部分的函数,如果它被该类的实例调用,它将自动神奇地将实例本身传递为第一个论点。注意,这里是特权的参数的位置,而不是名称​​ self ,这仅仅是约定。它可以是你想要的任何东西。名称甚至不必在类一致(但当然,在函数本身内是一致的)。我们称之为西葫芦,以获得乐趣:

In [8]: class WhyNot:
   ...:
   ...:     def __init__(self):
   ...:         self.foo_flag = False
   ...:         self.bar_flag = False
   ...:
   ...:     def foo(zucchini):
   ...:         print("I speak American English")
   ...:         zucchini.foo_flag = True
   ...:
   ...:     def bar(courgette):
   ...:         print("And British English")
   ...:         courgette.bar_flag = True
   ...:
In [9]: x = WhyNot()

In [10]: x.foo()
I speak American English

In [11]: x.bar()
And British English

In [12]: x.foo_flag
Out[12]: True

In [13]: x.bar_flag
Out[13]: True

但是请坚持惯例。

答案 3 :(得分:0)

在苏打课程中,关键词是“自我”。是指苏打的一个实例。简单地分开'苏打水对象在这里没有多大意义。你想要做的是在创建每个Soda对象时拆分字符串参数。

因此,更好的方法是在 init ()函数中将参数拆分为名称,价格和数量。

def __init__(self, args = "", _price = 0.0, _quantity = 0):
        args = args.split(",")
        self._name = args[0]
        self._price = args[1]
        self._quantity = args[2]

在getName函数中,顾名思义,最好只获取名称。

def getName(self) :
    return self._name

我希望这可以帮助你学习Python〜

答案 4 :(得分:0)

您实际上没有将字符串传递给sshgetName的地方。调用__init__不会传入任何字符串。

这是 init 期望(名称,价格,数字)而非字符串的情况。所以Pythonic就是添加一个静态方法self.getName()

from_string/make/make_from_string