如何在Python中使用@property decorator创建随机int列表并将其设置为值



我对装饰器的概念相当陌生。

我正在尝试实现一个函数,该函数创建一个随机整数列表,并将其设置为__init__方法中的group_list变量。

第二种方法接受用户的输入,并将其设置为__init__方法中的value变量。

class Order(object):
def __init__(self, group_list=None, value=None):
self.group_list=groupList
self.value=number
print(self.groupList)

@property
def groupList(self):
return self._groupList
@groupList.setter
def _groupList(self):
global list_val
for _ in range(10):
currentelement= randint(1,15)
list_val.append(currentelement)
self._groupList=list(set(list_val))
@property
def number(self):
return self._number
@number.setter
def number(self):
val=input('Enter any number from the list: ')
self._number=val

我在这里做错了什么?如有任何帮助,我们将不胜感激!

我知道在有限的时间内完成一项任务,并且必须等待问题的答案是什么感觉,所以当我今天休息的时候,我对你的问题做了很大的调整。我希望总的来说我能回答你的问题(我做错了什么?)。

请原谅我没有在代码块进进出出的部分详细说明所有内容,我当时有点着急。此外,在代码中完成所有注释后,您可以将其复制/粘贴到文件中并运行它

from random import randint
class Order(object):
# Notice that group_list is used several places, so in the parameters I'm changing it to g_list just to make
# it obvious which variable or parameter is being accessed
def __init__(self, g_list=None, value=None):
# Whenever calling a method inside of class, you have to reference the class
# itself as part of the call. So in this case the call should be `self.groupList`
#
# Pep8 calls for methods to be lower case rather than hump case, and when using python
# getter/setter (properties) you usually want to set a property with a different name (implied private) than
# the defined property (getter/setter).
#
# Notice a few things in the new call. The property name is made private, and the methods that are decorated
# with @property and @method.setter are NOT private or protected (see below). Also note that since
# We're calling the group_list property below we need to set a value (notice the list_val property
# in the setter below).
#
#
# NOTE: If we were to set the __group_list directly, we would not allow any of the code in the setter
# method to execute, possibly bypassing any data checking we wanted to do.
#
# self.group_list=groupList becomes:
self.__group_list = []  # defines the property we're going to use
self.group_list = g_list # calls the setter passing in the g_list parameter
# Again since you are accessing your properties with methods, make the value private or at least protected
# keep in mind that python's idea of private and protected methods is strictly a suggestion. There really
# isn't a private/protected method in python.
#
# Since at this point we're assuming a "value" was passed into the class, we can't call the
# setter, or it will ask for a number right away. If that's the goal, there are better ways to handle it.
# with the information provided in the question, it's best to just set this value directly. Of course you
# should verify the data first.
#
# self.__value=self.number
self.__value = value
# removed so not to cause confusion with example code outside object
# print(self.group_list)

@property
# Here the method is named according to what we want to access in our code. Also properly
# named using word_word format. The property decorator tells python to treat this as a
# getter, and return a value. In this case we're returning the value of the property we created in init.
#
# def groupList(self):
def group_list(self):
# here we change the name of the property to be returned to match the property we defined in the init
# return self._groupList
return self.__group_list
# The name of the property setter decorated must match the name of a method defined by the property
# decorator prior to the setter being defined.
#
# @groupList.setter
@group_list.setter
# The method name must match the method name used where you defined the property as mentioned above. Also
# notice that I added a parameter so that the list_val can be passed into the method.
# def _groupList(self):
#
# Please note that if you're not going to need to use the parameter on a "setter" you're better off
# not using the setter decorator and just renaming the method to something logical. In this case, something
# like "generate_list" would be perfect.
def group_list(self, list_val):
# Global values in python are global only to the module. Your code as I was typing this did not include any
# declaration of the list_val, and even if you have one defined, you should still pass in the value
# and more than likely do away with a global defined one.
#
# There is a place for module level variables of course, but they should be the exception not the rule when
# working with objects. Your code is much clearer, and is likely no less efficient by passing around references
# of lists.
#
# global list_val
if list_val is None:
for _ in range(10):
# You can do all of this in a single line. Notice though that I changed
# the property being set.
# currentelement= randint(1,15)
# list_val.append(currentelement)
# self._groupList=list(set(list_val))
self.__group_list.append(randint(1, 15))
elif isinstance(list_val, list):
self.__group_list = list_val
@property
def number(self):
# here again, we want to access the property we are setting.
#
# return self._number
return self.__value
# Setters require a signature of (self, value). You have a signature of (self) here. A setter is expecting
# that you will want to pass a value in to be set.
#
# Without knowing all the details involved I have to say that this code produces smell. It would likely be
# better to ask for the user input someplace else in your code and pass that value in to be stored or do something
# with it. Having a module or class devoted to user interaction (a View) is common. But having it mixed with
# application logic is usually bad.
#
# assuming you want to keep this request within the class here, this would be best renamed and not used
# as a setter.
#
# Again notice the change from _number to __value.
#
# Also note I added a conversation to integer on the user input. This assumes the user will always chose an
# integer. Of course checks should be put in place to validate all user input.
#
# @number.setter
# def number(self):
#     val=input('Enter any number from the list: ')
#     self._number=val
def ask_user_for_number(self):
val=input('Enter any number from the list: ')
self.__value=int(val)

# now I can use the class as such:
# If I pass no data in at instantiation a new list will be
print("Example with random list")
obj = Order()
obj.ask_user_for_number()
print("List of numbers: {}".format(obj.group_list))
print("User selected: {}".format(obj.number))
in_list = obj.number in obj.group_list
print(in_list)
# if I want to provide a list
print("-" * 10)
print("Example with fixed list")
my_list = [1,2,3,4,5,6,7,8,9,10]
my_obj = Order(g_list=my_list)
my_obj.ask_user_for_number()
print("List of numbers: {}".format(my_obj.group_list))
print("User selected: {}".format(my_obj.number))
in_my_list = my_obj.number in my_obj.group_list
print(in_my_list)

最新更新