简体   繁体   中英

Object Attribute in Random List Not Accessible in Python

I'm working on my first object oriented bit of python and I have the following:

#!/usr/bin/python 
import random 

class triangle:

# Angle A To Angle C Connects Side F
# Angle C to Angle B Connects Side D
# Angle B to Angle A Connects Side E

    def __init__(self, a, b, c, d, e, f):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f

    #def solver:
        #pass

#initialize Triangle
myTri = triangle(0,0,0,0,0,0)

#Pick Three Random Angles or Sides to Generate Values For
sample = random.sample([myTri.a, myTri.b, myTri.c, myTri.d, myTri.e, myTri.f],  3)

#Sets the three randomly picked variables to a Random Number



sample[0] = random.randint(1, 100)
sample[1] = random.randint(1, 100)
sample[2] = random.randint(1, 100)

How do I pass myTri.a, for example to random.randint. It is passing the value of '0' which it initialized. I want to be able to assign a random value to three of the .a-.f attributes of myTri. What am I missing?

When you say [myTri.a, myTri.b, ...] you are not getting a list of the variables themselves, or references to them. Instead you are getting just their values. Since you know they were initialized to 0 , it is as if you had written [0, 0, 0, 0, 0, 0] . There's no difference.

Then later when you try to assign to sample[0] , you are actually just overwriting the 0 that is stored in that array with a random value. Python knows nothing at all about myTri at that point; the connection is lost.

Here's what you can do to get the effect you're aiming for. First, pass a list of variable names we want to assign to later to random.sample :

sample = random.sample(["a", "b", "c", "d", "e", "f"], 3)

That'll give us back 3 random variable names. Now we want to assign to the variables with those same names. We can do that by using the special setattr function, which takes an object and a variable name and sets its value. For instance, setattr(myTri, "b", 72) does the same thing as myTri.b = 72 . So rewritten we have:

setattr(myTri, sample[0], random.randint(1, 100))
setattr(myTri, sample[1], random.randint(1, 100))
setattr(myTri, sample[2], random.randint(1, 100))

The major concept here is that you're doing a bit of reflection, also known as introspection. You've got dynamic variable names--you don't know exactly who you're messing with--so you've got to consult with some more exotic, out of the way language constructs. Normally I'd actually caution against such tomfoolery, but this is a rare instance where introspection is a reasonable solution.

To assign to a , b , and c :

myTri.a = random.randint(1, 100)
myTri.b = random.randint(1, 100)
myTri.c = random.randint(1, 100)

To assign to one random attribute from a - f :

attrs = ['a', 'b', 'c', 'd', 'e', 'f']
setattr(myTri, random.choice(attrs), random.randint(1, 100))

To assign to three random attributes from a - f :

attrs = ['a', 'b', 'c', 'd', 'e', 'f']
for attr in random.sample(attrs, 3):
  setattr(myTri, attr, random.randint(1, 100))

Alternative to using setattr: do it when you create a Triangle instance.

args = [random.randint(1, 100) for i in xrange(3)] + [0, 0, 0]
random.shuffle(args)
my_tri = Triangle(*args)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM