Как создать список случайных int и установить его в качестве значения, используя @property decorator в Python? - PullRequest
0 голосов
/ 11 февраля 2019

Я довольно новичок в концепции декораторов.

Я пытаюсь реализовать функцию, которая создает список случайных целых чисел и задает для него переменную group_list в методе __init__.

И второй метод берет ввод от пользователя и устанавливает его в переменную value в методе __init__.

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

Что я здесь не так делаю?Любая помощь будет высоко оценена!

1 Ответ

0 голосов
/ 12 февраля 2019

Я знаю, что значит пытаться выполнить задание в ограниченное время, и мне приходится ждать ответов на вопросы, поэтому я очень серьезно отнесся к вашей проблеме, пока у меня было немного простоя сегодня.Я надеюсь, что в целом мне удалось ответить на ваш вопрос (Что я здесь не так делаю?).

Простите, что я не все подробно описываю в разделах, входящих и выходящих из блоков кода, я немного спешил,Кроме того, со всеми комментариями, сделанными в коде, вы можете скопировать / вставить это в файл и запустить его.Это предполагает python3 +

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)
...