用Python类开发

用Python类开发,python,Python,没有什么比Python类概念更让我害怕的了;最近我一直在尝试使用/创建类来理解它们的用途、结构和功能等。但是,我不清楚类的概念以及如何创建它们 请看以下示例: class Prob(object): def __init__ (self,filename): self.file_contents = read_file(filename) def prob_build(self): self.problem, self.aux_vars = bui

没有什么比Python类概念更让我害怕的了;最近我一直在尝试使用/创建类来理解它们的用途、结构和功能等。但是,我不清楚类的概念以及如何创建它们

请看以下示例:

class Prob(object):
    def __init__ (self,filename):
        self.file_contents = read_file(filename)
    def prob_build(self):
        self.problem, self.aux_vars = build_problem(file_contents)

first_object = Prob(some_file)
alpha,beta, gamma = first_object.prob_build() 
在这种情况下,
read_file
build_problem
分别是从CSV文件读取数据和构建基于纸浆的线性问题的自定义函数。现在,我的理解是,当我基于
Prob
类初始化对象时,该类可以在内部使用文件内容。在这种情况下,如何获取变量
alpha
beta
gamma
?对于当前代码,我得到了一个
TypeError:“NoneType”对象是不可编辑的。
我已经测试了这些函数,并且知道它们可以正常工作,这让我觉得我定义类的方式有问题


有什么建议吗

类似于普通的
函数
,类
方法
需要返回一些东西才能得到结果!在您的代码中,
prob\u build
不会返回任何内容!所以,应该是这样的:

def prob_build(self):
    self.problem, self.aux_vars = build_problem(file_contents)
    return (self.problem, self.aux_vars)

注意,在本例中,它返回两个参数。您应该更具体地说明什么是
alpha
beta
gamma

类似于普通的
函数
,类
方法
需要返回一些东西才能得到结果!在您的代码中,
prob\u build
不会返回任何内容!所以,应该是这样的:

def prob_build(self):
    self.problem, self.aux_vars = build_problem(file_contents)
    return (self.problem, self.aux_vars)

注意,在本例中,它返回两个参数。您应该更具体地说明什么是
alpha
beta
gamma

类函数prob_build()不返回任何内容。它只设置类内部的变量

类函数prob_build()不返回任何内容。它只设置类内部的变量

您的
prob\u build
方法需要
返回三个值。您当前没有显式地
return
ing任何内容,因此它隐式地返回单个值
None
,Python试图将其解析为三个值,但显然失败了

这与这是一个类的方法这一事实无关;函数返回值,无论它们是如何定义的,在何处定义的


当然,函数不返回任何内容是完全可以的;但是很明显,它不会产生像
variable=func()

这样的结果,您的
prob\u build
方法需要
返回三个值。您当前没有显式地
return
ing任何内容,因此它隐式地返回单个值
None
,Python试图将其解析为三个值,但显然失败了

这与这是一个类的方法这一事实无关;函数返回值,无论它们是如何定义的,在何处定义的

当然,函数不返回任何内容是完全可以的;但是很明显,它不会产生像
variable=func()

没有什么比Python类概念更让我害怕的了

这实际上不是Python的概念——类存在于大多数面向对象语言中

最近我一直试图(…)理解它们的目的、结构和特点等。但是,我不清楚类的概念

在我们讨论类之前,您必须了解对象。对象是将状态(一组数据)和行为(作用于状态或根据状态的一组函数)组合在一起的一种方式。现在这是一个抽象的定义,让我们看看它是如何与一个简单的例子-一个二维空间中的几何点

对于状态零件,二维点由其x和y坐标定义。您可以用一个
dict
表示这一点:

my_point = {"x": 0, "y": 0}
好的,很好,但不是很明确,而且容易出错。我们可以从负责创建新点的函数开始:

def new_point(x=0, y=0):
    return {"x": x, "y": y}

p1 = new_point()
p2 = new_point(42, 84)
现在我们可以不必担心血淋淋的细节而建立积分。好的,现在让我们做一点行为。。。第一个有用的功能是检查两个点是否相等(如果它们具有相同的坐标,则假设它们相等):

您可以看到,此行为取决于两个点状态

我们还可以沿水平轴移动一个点:

def move_x(p, distance):
    p["x"] += distance
或沿垂直轴:

def move_y(p, distance):
    p["y"] += distance
或两者同时进行:

def move_by(p, x_distance, y_distance):
    move_x(p, x_distance)
    move_y(p, y_distance)           
请注意,此处的行为是更改点的状态

当然,我们需要一种方法来获得点的x或y坐标:

def points_are_equal(p1, p2):
    return p1["x"] == p2["x"] and p1["y"] == p2["y"]
 def get_x(p):
     return p["x"]

 def get_y(p)
     return p["y"]
我们在这里构建的是所谓的“抽象数据类型”:我们没有手动构建dict,手动比较两个dict,手动更新dict并手动检查其状态,而是定义了一个set a函数来完成所有这些,或多或少地隐藏内部表示

以及如何创建它们

大多数情况下,班级是做同样事情的另一种方式,但也有很多其他的好处。让我们将“点”数据类型重写为Python类:

class Point(object):
    # this is the function that creates a new point
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    # equality test:
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    # move
    def move_x(self, distance):
        self.x += distance

    def move_y(self, distance):
        self.y += distance

    def move_by(self, x_distance, y_distance):
        self.move_x(x_distance)
        self.move_y(y_distance)
我们实际上不需要编写
get_x()
get_y()
,我们可以直接访问x和y:

p = Point(2, 5)
print(p.x)
print(p.y)

p.move_by(3, 1)
print(p.x)
print(p.y)

p2 = Point(p.x, p.y)
print(p == p2) # => True
p2.move_x(3)
print(p == p2) # => False
实际上,在引擎盖后面,我们的
p
对象是一个dict:

其他OOPL可能使用其他方式来存储对象的状态(例如,类似C语言的结构),但在Python中,对象实际上主要是dict。dict加上类:

print(p.__class__)
以及一组“属性查找规则”(由基类
对象提供),首先在对象的
上查找属性,然后在对象的类上查找属性(这就是
p.move\ux(42)
实际解释为
Point.move\ux(p,42)

类和对象
def prob_build(self):
    self.problem, self.aux_vars = build_problem(self.file_contents)
first_object = Prob(some_file)
first_object.prob_build() 
print(first_object.problem)
print(first_object.aux_vars)
first_object = Prob(some_file)
# Doesn't work !!!
print(first_object.problem)
class Prob(object):
    def __init__ (self,filename):
        self.file_contents = read_file(filename)
        self.problem = None
        self.aux_vars = None

    def prob_build(self):
        self.problem, self.aux_vars = build_problem(self.file_contents)
class Prob(object):
    def __init__ (self,filename):
        self.file_contents = read_file(filename)
        self.problem, self.aux_vars = build_problem(self.file_contents)
 prob = Prob("path/to/file.csv")
 prob, aux_vars = prob.problem, prob.aux_vars
 result = do_something_with(prob, aux_vars)
def build_problem_from_file(path):
    return build_problem(read_file(path))

 prob, aux_vars = build_problem_from_file(...)
 result = do_something_with(prob, aux_vars)
class Prob(object):
    def __init__ (self,filename):
        self.file_contents = read_file(filename)
        self.problem, self.aux_vars = build_problem(self.file_contents)

     def do_something(self):
         # some computations here using self.problem and self.aux_vars
         return result  

 prob = Prob("path/to/file.csv")
 result = prob.do_something()
def build_problem_from_file(path):
    return build_problem(read_file(path))

 def resolve_problem_from_file(path):
     prob, aux_vars = build_problem_from_file(...)
     return do_something_with(prob, aux_vars)

 result = resolve_problem_from_file(...)