简体   繁体   English

如何对字符串进行split()并将其传递给对象的__init __()方法?

[英]How to to split() a string and pass it into an object's __init__() method?

I am trying to create multiple instances of a Soda object using information from a file. 我正在尝试使用文件中的信息创建一个Soda对象的多个实例。 The file is formatted like this Name,price,number 该文件的格式如下:名称,价格,编号

Mtn. Dew,1.00,10

Coke,1.50,8

Sprite,2.00,3

My code I have is this (this is a function within main()): 我的代码是这样的(这是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

If I got this right, popMachine should be a list of 3 different Soda objects, each with one line of the input file. 如果我做对了,popMachine应该是3个不同的Soda对象的列表,每个对象有一行输入文件。

Within my class, I then need to be able to get just the name or price or quantity for use in calculations later. 然后,在我的课堂上,我需要能够仅获取名称,价格或数量以供以后进行计算。 My class Sodas code looks like this: 我的类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

This is where I run into problems. 这是我遇到问题的地方。 IIRC self stands in place of line in the main code, so self should be a string such as "Mtn. Dew,1.00,10" and the expected outcome of the split(",") method should form a list like ["Mtn. Dew", "1.00", "10"] where I can then use the index of that list to return just the name. IIRC self代表主代码中的行,因此self应该是一个字符串,例如“ Mtn。Dew,1.00,10”,并且split(“,”)方法的预期结果应形成一个类似于[“ Mtn 。Dew“,” 1.00“,” 10“],然后我可以使用该列表的索引仅返回名称。

However, I get this error "AttributeError: Soda instance has no attribute 'split'" And I'm not sure why. 但是,我收到此错误“ AttributeError:苏打水实例没有属性'split'”,但我不确定为什么。 Also, all the comments in this code came from my instructor as part of the assignment, so even if there are quicker/better methods for doing this whole thing, this is the way I have to do it :/ 另外,此代码中的所有注释都来自我的老师,作为作业的一部分,因此,即使有更快/更好的方法来完成这件事,这也是我必须这样做的方法:/

The self variable refers to the object instance . self变量是指对象实例 What you can do is to either split the line in the constructor like so 你可以做的是要么在构造分割线,像这样

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

...or you can split it lazily when asked for it ...或者您可以在要求时懒散地分割它

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

Note that in python variables such as function names are usually snake_case by convention. 请注意,在python中,按照惯例,函数名称之类的变量通常是snake_case

When you use self , you refer to the instance of Soda , and since you have not defined a split method, it will not have one. 使用self ,将引用Soda的实例,并且由于尚未定义split方法,因此它将没有一个。

You can simply use unpacking to pass the result of split to the class. 您可以简单地使用拆包将split的结果传递给类。

You may want to add in some checks to make sure that unpacking returns three values, although since you use default arguments it will only error out if you provide more than three values. 您可能希望在一些检查添加,以确保开箱回报三个值,虽然因为你使用默认参数,将唯一的错误,如果你提供超过三个值。

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)

Output: 输出:

Mtn. Dew
Coke
Sprite

You could even define a helper method that returns a Soda instance from a line in your file: 您甚至可以定义一个帮助程序方法,该方法从文件中的一行返回一个Soda实例:

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

Which you can call using: 您可以使用以下方式致电:

Soda.make_soda(line)

IIRC self stands in place of line in the main code, so self should be a string such as "Mtn. Dew,1.00,10" and the expected outcome of the split(",") method should form a list like ["Mtn. Dew", "1.00", "10"] where I can then use the index of that list to return just the name. IIRC self代表主代码中的行,因此self应该是一个字符串,例如“ Mtn。Dew,1.00,10”,并且split(“,”)方法的预期结果应形成一个类似于[“ Mtn 。Dew“,” 1.00“,” 10“],然后我可以使用该列表的索引仅返回名称。

Hold up just a minute. 等一下 This is a common misconception when people are learning to code. 当人们学习编码时,这是一个普遍的误解。 Fundamentally, you are conflating your source code with the data-type str . 从根本上讲,您正在将源代码与数据类型str混合在一起。 This is an easy mistake to make, for indeed, one creates a text-file when one is writing source code. 这是一个容易犯的错误,因为的确在编写源代码时创建了一个文本文件。 One writes text into the file, and one can even load that in Python ( open('my_script.py').read()) and we get a string! 一个人将文本写入文件,甚至可以在Python中加载文本( open('my_script.py').read()) ,我们得到一个字符串! And yes, strings are consumed by the programs you run when your source code takes the journey from your programming language to machine code. 是的,当源代码从编程语言过渡到机器代码时,字符串将被您运行的程序所占用。 But I advocate that you keep these two things separate in your mind. 但是我主张您将这两件事分开记住。 Your source code is not a string . 您的源代码不是字符串 It should sit "above" it conceptually (and anyway, we are dealing in useful abstractions here). 它应该在概念上位于“上方”(无论如何,我们在这里处理有用的抽象)。 So, while your idea is essentially correct, 因此,虽然您的想法本质上是正确的,

self stands in place of line in the main code 自我代表主代码中的行

But here "the line" means what the line refers to , the piece of logic executed by your code, not literally the line of code you write. 但是这里的“行”表示该行所指的是代码执行的逻辑部分,而不是您编写的代码行。 So, self refers to the object instance when the method is executed by an instance of the class. 因此,当方法由类的实例执行时, self指的是对象实例

So, self is not a string . 因此, self 不是字符串 It is an object of the type your class is defining. 它是您的类正在定义的类型的对象。 Your class doesn't have that method. 您的课程没有该方法。 str objects do. str对象呢。

Here's a little look at the python data model. 这里稍微看一下python数据模型。 "self" is quite straight-forward. “自我”很简单。 The instance itself is passed as an argument. 实例本身作为参数传递。 This is done under the covers for you by "magic" (magic that you can learn to play with later) but essentially, my_instance.some_method() is mostly equivalent to MyClass.some_method(my_instance) 这是通过“魔术”(您可以稍后学习玩的魔术)在my_instance.some_method() ,但从本质my_instance.some_method()my_instance.some_method() 基本上等同MyClass.some_method(my_instance)

So consider, 所以考虑一下

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!

A method is merely a function that is part of a class, and if it get's called by an instance of that class, it will auto-magically get the instance itself passed as the first argument. 方法只是属于类的一部分的函数,如果该方法被该类的实例调用,它将自动神奇地获取实例本身作为第一个参数传递。 Note, it is the position of the argument that is privileged here, not the name self which is merely convention. 请注意,这里是特权的参数位置,而不是名称self ,这仅仅是约定。 It can be whatever you want. 它可以是任何您想要的。 The names don't even have to be consistent within the class (but of course, consistent within the function itself). 名称甚至不必在类内保持一致 (当然,在函数本身内也保持一致)。 Let's call it zucchini for fun: 我们称它为西葫芦很有趣:

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

But please, stick to convention. 但是请遵守惯例。

In the class Soda, the key word 'self' refers to an instance of Soda. 在Soda类中,关键字“ self”是Soda的实例。 Simply 'split' a Soda object does not make much sense here. 只是简单地“拆分”苏打物体在这里没有多大意义。 What you want to do is actually to split the string arguments at the creation of each Soda object. 您实际上想要做的是在创建每个Soda对象时拆分字符串参数。

Therefore, a better way is to split arguments into name, price and quantity in the init () function. 因此,更好的方法是在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]

While in the getName function, as the name suggests, it is better to only fetch the name. 顾名思义,在getName函数中,最好仅获取名称。

def getName(self) :
    return self._name

I hope this can help you in your way learning Python~ 我希望这可以帮助您学习Python〜

There's no place you actually pass in a string to either getName or __init__ . 您实际上没有将字符串传递给getName__init__ Calling self.getName() is not passing in any string. 调用self.getName()不会传递任何字符串。

This is a case where init will expect (name,price,number), not a string. 在这种情况下, init会期望(名称,价格,数字),而不是字符串。 So the Pythonic thing is to add a staticmethod from_string/make/make_from_string : 因此,Python式的事情是添加一个静态方法from_string/make/make_from_string

class Soda:
    def __init__(self, name = '', price = 0.0, quantity = 0) :
            self._name = name
            self._price = price
            self._quantity = quantity

    @staticmethod
    def from_string(s):
        return Soda(s.split(','))


 >>> Soda.from_string('Mtn. Dew,1.00,10')
 <__main__.Soda object at 0x107428f60>
 # Success! Mind you, your class could do with a __str__() method now...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在实例化 object 时传递 **kwargs 并在类的 __init__() 方法中访问它 - How do I pass **kwargs when instantiating an object and access it in the class's __init__() method 如何将参数传递给Python的HTMLParser __init__方法 - How to pass parameters to Python's HTMLParser __init__ method object 和 __init__ 方法 - object and __init__ method 在 python 27 中,如何将带参数的方法传递给类的 __init__()? - In python 27 how do I pass a method with arguments to a class's __init__()? 如何自动将变量传递给类__init__方法? - How to pass a variable to a class __init__ method automatically? 如何通过调用__init__方法中的方法在python中引入对象的属性? - How to introduce the attributes of an object in python by calling a method in __init__ method? 如何从声明的描述符生成类的 __init__ 方法? - How to generate class's __init__ method from declared descriptors? 如何命名__init__用于确定新对象的值的方法? - How to name method used by __init__ to determine value of new object? 如何对Enum的__init__方法进行单元测试? - How can I unittest an Enum's __init__ method? 如何使用具有 __init__ 方法的子类创建一个空的 object? - How to create an empty object with child classes that have __init__ method?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM