--- tags: Python --- # Python Self-Check 10 CS 1358 Introduction to Programming in Python Fall Semester 2022 Prof. Pai H. Chou Self-Check 10 Due Date: -- Answer the following questions to check your understanding of your material. Expect the same kind of questions to show up on your tests. For this course, we use vi and vim interchangeably. ## 1. Definitions and Short Answers 1. In Python, suppose you have the code return [13, 25, 'hello', 'z'] Which of the following are objects? ``` a. return //No b. 13 //Yes c. 25 //Yes d. 'hello' //Yes e. 'z' //Yes f. [13, 25, 'hello', 'z'] //Yes g. , //No ``` 2. In Python, do the following keywords or built-in identifiers refer to objects? ``` a. if //keywords b. print //identifiers c. len //identifiers d. str //identifiers e. == //keywords ``` 3. How can you make a clone of an object? ``` import copy x = copy.copy(y) # shallow copy x = copy.deepcopy(y) # deep copy ``` 4. What is a class? How is a class related to an instance? ``` class: member data and code (member function) that operates on data instance: object created according to class ``` 5. What is the term for a function call whose name is the name of a class? ``` constructor ``` 6. How is a method different from a function? ``` method is a function in class ``` 7. When you do ``` import os L = os.listdir() ``` are you making a method call with os.listdir(), or are you making a function call? Why? ``` method call, because os.listdir() is the way of calling method ``` 8. In Python, suppose you have a class defined as ``` class Point: def __init__(self, x, y): self.x = x self.y = y def move_by(self, dx, dy): self.x += dx self.y += dy ``` ``` a. How do you instantiate a point with a coordinate of (2, 3) and assign it to the variable p? //p = Point(2, 3) b. What are the two attributes created by the constructor of this point? //x, y c. The move_by() method defines three parameters (self, dx, dy) but the call takes only two arguments, such as p.move_by(-2, 7). Why? //because method call need to include parameter self d. Is it ever okay to declare an instance method without any parameter, such as def sayhi(): print("I am a point") ? //No ``` 9. How would you define the \_\_repr__ method for the Point class above? What should it display if p = Point(2, 3) and you type p at the interactive prompt? ``` def __repr__(self): return f"Point({self.x}, {self.y})" ``` 10. Suppose in your class definition, ``` class Point: def __init__(self, x, y): self.x = x self.y = y def move_by(self, dx, dy): self.x += dx self.y += dy m = move_by @property def area_of_box(self) return self.x * self.y ``` ``` a. What is the effect of line 8? //declares m to be an alias move_by b. What type of construct is the @property on line 9? //let area_of_box just name derived attributes without the calling () syntax c. With line 9, how should you invoke the code for area_of_box on a Point object p? //p.area_of_box d. What is the purpose of applying the @property decorator here? // 1.uniform syntax like regular attributes 2.can make attribute read-only access ``` 11. Suppose you have ``` >>> p = Point(2, 3) >>> q = Point(4, 5) >>> p.z = 7 ``` ``` a. What happens when you try to readf the value of q.z? //AttributeError b. if you set q.z = 10, what happens to the value of p.z? //Nothing c. Is it okay if you do Point.count = 0 next? If so, what kind of attribute is it called? //It is OK, the class's namespace d. Assuming the assignment Point.count = 0 is allowed, what is the value of p.count? Is it defined? //0, it define in class Point e. What is the value of dir(p)? Does it include 'count' as a key in this dict? What about dir(q)? // dir(p): {....., 'x', 'y', 'z'} No dir(q): {....., 'x', 'y', 'z'} ``` 12. If you want your constructor to increment a class attribute to count the number of instances created so far, ``` a. How should you initialize the class attribute count = 0? // class Point(): count = 0 #class attribute b. How should you increment the class attribute count in the constructor? As self.count += 1 or as Point.count += 1? Why? //Point.count += 1, because self.count += 1 only will be called once ``` 13. Why is it better to define setter/getter methods than allowing user code to modify the attributes directly? For instance, suppose you have a DateTime class that allows you to do ``` >>> dt = DateTime(year=2019, month=11, day=11, hour=9, \ ... minute=8, second=7) >>> dt.set_year(2023) Why would it be preferred, compared to >>> dt.year = 2023 ? ``` ``` limit allowed values of attributes ``` 14. In DateTime class shown on slide #35, the attributes are named with an underscore in front, such as _year, _month, _day, etc. What is the reason for this? ``` use _ to protect attribute from outside access ``` 15. In the DateTime class, the check_and_set() method is defined to be ``` def check_and_set(self, field_name, field_value, L, U): if not (L <= field_value <= U): raise ValueError(f'{field_name} must be {L}..{U}') self.__dict__['_'+field_name] = field_value ``` ``` a. What is the purpose of self.__dict__['_'+field_name] = field_value? If field_name is 'year', self is p, and field_value is 2010, then what attribute of p gets assigned the value 2010? // to change attribute value p._year b. Why is it a good idea to write check_and_set() as a method that is called by set_year(), set_month(), set_day(), etc methods to assign value via self.__dict__[] instead of assigning to the attributes self._year, self._month, self._day directly? // reduce the code ``` 16. Assume you have a getter and a setter for the instance attribute _month in the DateTime class: ``` class DateTime: def get_month(self): ... def set_month(self, mo): ... month = property(lambda self: self.get_month(), lambda self, v: self.set_month(v)) ``` What is the effect of lines 6-7? Suppose you have a variable dt which is an instance of DateTime, what method gets called when you do ``` print(dt.month) ``` and ``` dt.month = 5 ``` ? ``` package getter/setter as attribute access print(dt.month): self.get_month() dt.month = 5: self.set_month() ``` 17. Which of the following correctly describes a class method? Assume you want to declare one named set_year_range() for the DateTime class and it takes parameters for the lower and upper bounds. ``` a. you need to use the decorator @classmethod on the line immediately before def set_year_range() method definition to make it a class method //Yes b. As long as you have the @classmethod decorator, the class method works just like an instance method because you would declare it as def set_year_range(self, lower, upper): and self refers to the instance that you invoke the method on. //NO, self need to replace by cls and cls refers to class c. In addition to @classmethod decorator, you also need to declare the first parameter as cls instead of self because it refers to the class object instead of the instance object //Yes d. Even though you want cls to refer to the class object, you still invoke the class method on an instance object (e.g., named p) p.set_year_range(100, 3000) and Python will pass the class object for p as the cls parameter //Yes ``` 18. Consider the leap-year function ``` def leap(year): return (year % 400 == 0) or \ ((year % 4 == 0) and (year % 100 != 0)) ``` and you would like to define it as a method inside the class DateTime rather than as a function outside the class. a. define it as an instance method ``` class DateTime: def leap(self, year): return (year % 400 == 0) or \ ((year % 4 == 0) and (year % 100 != 0)) ``` b. define it as a class method ``` class DateTime: @classmethod def leap(cls, year): return (year % 400 == 0) or \ ((year % 4 == 0) and (year % 100 != 0)) ``` c. define it as a static method ``` class DateTime: @staticmethod def leap(year): return (year % 400 == 0) or \ ((year % 4 == 0) and (year % 100 != 0)) ``` d. Is there any difference in how you would call the leap method? ``` No ``` e. Which of the three methods would be the preferred way and why? | | Pro | Con | | -------- | --------------------------------------------------------- | --------------------------- | | instance | defined like method | self is passed but not used | | class | defined like method | cls is passed but not used | | static | no name pollution <br> does not pass cls or self unnecessarily | |