如何在python中评估类级别的属性值?

时间:2019-06-09 06:38:29

标签: python

我具有以下类结构:

class StarCount:
    one_stars = 0
    two_stars = 0
    three_stars = 0
    four_stars = 0
    five_stars = 0

class OrientationAnalysis:
    straight = StarCount()
    bisexual = StarCount()
    gay = StarCount()

class GenderAnalysis:
    men = OrientationAnalysis()
    women = OrientationAnalysis()

我编写了以下代码:

genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100

print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is also 100

为什么genderanalysis.women.straight.five_stars也被更新?我也检查了genderanalysis.women.gay.five_stars,但是它没有更新吗?

4 个答案:

答案 0 :(得分:3)

在类的init方法中定义值,以使它们附加到实例对象,而不是类对象本身。

class StarCount:
    def __init__(self):
        self.one_stars = 0
        self.two_stars = 0
        self.three_stars = 0
        self.four_stars = 0
        self.five_stars = 0

class OrientationAnalysis:
    def __init__(self):
        self.straight = StarCount()
        self.bisexual = StarCount()
        self.gay = StarCount()

class GenderAnalysis:
    def __init__(self):
        self.men = OrientationAnalysis()
        self.women = OrientationAnalysis()

genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100

print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is now 0

答案 1 :(得分:3)

当您声明一些这样的变量时:

class StarCount:
    one_stars = 0
    two_stars = 0
    three_stars = 0
    four_stars = 0
    five_stars = 0

这些变量变为class变量。 Class变量是类的所有实例共享的变量。因此,当您更新genderanalysis.men.straight.five_stars时,它实际上更新了StarCount.five_stars,并且由于genderanalysis.women.straight.five_stars也指向相同的变量,因此它似乎也已更新。

我认为您正在寻找的是instance variables。您可以这样声明它们:

class StarCount:
    def __init__(self):
        self.one_stars = 0
        self.two_stars = 0
        self.three_stars = 0
        self.four_stars = 0
        self.five_stars = 0

修改

  

为什么genderanalysis.women.gay.five_stars未更新?

发生的事情是,在更新genderanalysis对象的任何变量之前,所有变量都指向StarCount类的变量。如您所见,它们具有相同的id

print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229389744'
print(id(genderanalysis.women.gay.five_stars)) # prints '94016229389744'

但是当您更改genderanalysis.men.straight.five_stars时,引用/指针将替换为您提供的值,在这种情况下为100。您可以看到他们的ID的不同:

print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', see the difference?

因此,现在genderanalysis.men.straight.five_stars并不指向StarCount.five_stars,而是指向OrientationAnalysis.straight.five_stars。再次,让我们检查一下他们的ID:

print(id(OrientationAnalysis.straight.five_stars)) # prints '94016229391328'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', same right?

现在就您的问题而言,genderanalysis.women.gay.five_stars仍未被触及,因此它指向StarCount.five_stars,因此它仍显示0。更改StarCount.five_stars,您会看到反映在genderanalysis.women.gay.five_stars中的更改。

StarCount.five_stars = 101
print(genderanalysis.women.gay.five_stars) # prints `101`

答案 2 :(得分:1)

您的属性不应为类属性,而应为实例属性。这将是您的起点:

class StarCount:
    def __init__(self, five_stars=0):

        self.five_stars = five_stars
        # ...


class OrientationAnalysis:
    def __init__(self):

        self.straight = StarCount()
        # ...


class GenderAnalysis:
    def __init__(self):

        self.men = OrientationAnalysis()
        self.women = OrientationAnalysis()

答案 3 :(得分:0)

您快到了,您正在引用和修改类变量,而不是实例变量。

您需要一个__init__(self)方法,并在self上创建所有属性