︠4f58aad8-aa03-4417-90a5-ffaec91c96das︠ ### Object-oriented programming ︡d77a1700-2a1a-4739-a948-da4bf692c9a4︡{"done":true}︡ ︠860348a5-7c41-4936-a49f-29c3fcf67997s︠ ### class: objects with the same structure and properties ### e.g., integer, Permutation, graph ### type and class are interchangeable in Python 3 (but here is Python 2) type(1.5) type(Permutation([1,3,2])) type(matrix([[1,2,3],[1,2,3]])) ︡052d8bf1-34e9-447d-8a01-33ee6c3ea0e3︡{"stdout":"\n"}︡{"stdout":"\n"}︡{"stdout":"\n"}︡{"done":true}︡ ︠3dcb4f84-36b1-4a77-a6fd-cd184d881614s︠ ### define a class called "fraction" ### __init__ takes some inputs and create an object in the class class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b q = fraction(1,2) print q.numerator print q.denominator ︡5eddda28-fcb6-4ef9-a8f3-c1d9a5067a72︡{"stdout":"1\n"}︡{"stdout":"2\n"}︡{"done":true}︡ ︠dd1af390-0ab1-4b32-8cb1-5e6f612354e8s︠ ### an instance of a class is an object isinstance(q,fraction) ︡0343f8fc-fc95-4c23-8998-7523ff1ad9d8︡{"stdout":"True\n"}︡{"done":true}︡ ︠2babc474-556a-4686-bb22-7a5bdc26036es︠ ### each object can be associated with many attributes defined by the user ### such as numerator, denominator, etc. class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) q = fraction(4,6) q.gcd ︡c59a23e1-2ae6-4348-8db7-1e7b4e36866e︡{"stdout":"2\n"}︡{"done":true}︡ ︠407baad3-1d24-44dd-835d-691c4a2d02c5s︠ ### functions associated with an object are called a method class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) q = fraction(2,3) print q.numerator print q.denominator p = q.reciprocal(); print p.numerator print p.denominator ︡168c4990-bbfa-417a-9636-16b47e143d8b︡{"stdout":"2\n"}︡{"stdout":"3\n"}︡{"stdout":"3\n"}︡{"stdout":"2\n"}︡{"done":true}︡ ︠566e072b-8647-4119-843a-e3a953f7b104s︠ ### Methods are callable [with ()] ### while attributes are not [without ()] q.numerator() ︡8045c983-d2ac-4f53-9ddd-315685e2b5fc︡{"stderr":"Error in lines 1-1\nTraceback (most recent call last):\n File \"/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py\", line 1188, in execute\n flags=compile_flags) in namespace, locals\n File \"\", line 1, in \nTypeError: 'sage.rings.integer.Integer' object is not callable\n"}︡{"done":true}︡ ︠9e2a55a0-d193-4332-88ae-46a8aaae0e72s︠ ### remark: _ is just a normal character without special meaning ### so it can also be a variable for _ in range(10): print _ ︡cfd1f6e4-3451-4bb0-a644-db0c6d917d33︡{"stdout":"0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n"}︡{"done":true}︡ ︠1ea47473-a5e7-4be0-804c-62811905205fs︠ ### there are many special methods in Python ### e.g., __init__, __repr__, __add__, __contain__ ### __repr__ tells Python what to print ### (the meaning of print) class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) def __repr__(self): return "{} / {}".format(self.numerator,self.denominator) q = fraction(2,3) print q ︡2fcb3eaa-c0d7-47ea-b285-2c0d967b5271︡{"stdout":"2 / 3\n"}︡{"done":true}︡ ︠2519dc1d-6351-41cd-a6d5-aa30a2819f08s︠ ### __add__ tells Python how to add ### (the meaning of + ) ### Similarly, ### __sub__ for substraction - ### __mul__ for multiplication * ### __div__ for division / class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) def __repr__(self): return "{} / {}".format(self.numerator,self.denominator) def __add__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return fraction( a*d + b*c, b*d) q = fraction(2,3) print q p = fraction(2,5) print p print p+q ︡b2e9e3a7-1a0c-47e8-9c6e-f9a6a64d2dbd︡{"stdout":"2 / 3\n"}︡{"stdout":"2 / 5\n"}︡{"stdout":"16 / 15\n"}︡{"done":true}︡ ︠66722066-a482-40b3-becc-988bcb73ac39s︠ ### __eq__ tells Python when two objects are the same ### (the meaning of == ) ### Similarly, ### __ne__ for not equal != class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) def __repr__(self): return "{} / {}".format(self.numerator,self.denominator) def __add__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return fraction( a*d + b*c, b*d) def __eq__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return a*d == b*c q = fraction(2,3) print q p = fraction(4,6) print p print p == q ︡119e5d8e-8ced-4f83-9816-067aedf209c6︡{"stdout":"2 / 3\n"}︡{"stdout":"4 / 6\n"}︡{"stdout":"True\n"}︡{"done":true}︡ ︠55d536ab-e89c-40c5-ac77-1edfdd15952cs︠ ### __le__ tells Python when one object is less than or equal to the other object ### (the meaning of <= ) ### Similarly, ### __lt__ for less than < ### __ge__ for greater than or equal to >= ### __gt__ for greater than > class fraction: def __init__(self,a,b): self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) def __repr__(self): return "{} / {}".format(self.numerator,self.denominator) def __add__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return fraction( a*d + b*c, b*d) def __eq__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return a*d == b*c def __le__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator if b*d < 0: return a*d >= b*c if b*d > 0: return a*d <= b*c q = fraction(2,3) print q p = fraction(5,6) print p print p <= q print q <= p ︡58f4c2da-cd8f-4e73-bd5c-8b7881d10674︡{"stdout":"2 / 3\n"}︡{"stdout":"5 / 6\n"}︡{"stdout":"False\n"}︡{"stdout":"True\n"}︡{"done":true}︡ ︠7c21a5bf-a935-40c0-8335-b8965672900fs︠ ### use dir to check all attributes and methods of an object ### e.g., the integer 1 has lots of attributes and methods dir(q) ︡6c81044d-4f57-4986-ab74-6203896d34b4︡{"stdout":"['__add__', '__doc__', '__eq__', '__init__', '__le__', '__module__', '__repr__', 'denominator', 'gcd', 'numerator', 'reciprocal']\n"}︡{"done":true}︡ ︠c9b9621b-f8a9-432d-8811-e6c45c7e37f6s︠ ### the class 'integer' has a lot of attributes dir(1) ︡a64a31c8-a154-4712-9917-3218db7b66f9︡{"stdout":"['__abs__', '__add__', '__and__', '__array_interface__', '__class__', '__copy__', '__delattr__', '__dir__', '__div__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getmetaclass__', '__getstate__', '__gt__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__le__', '__long__', '__lshift__', '__lt__', '__mod__', '__module__', '__mpz__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pari__', '__pos__', '__pow__', '__pyx_vtable__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setstate__', '__sizeof__', '__slots__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', '_act_on_', '_acted_upon_', '_add_', '_add_parent', '_ascii_art_', '_axiom_', '_axiom_init_', '_bnfisnorm', '_cache_key', '_cmp_', '_coeff_repr', '_div_', '_divide_if_possible', '_doccls', '_dummy_attribute', '_exact_log_log2_iter', '_exact_log_mpfi_log', '_floordiv_', '_fricas_', '_fricas_init_', '_gap_', '_gap_init_', '_giac_', '_giac_init_', '_gp_', '_gp_init_', '_im_gens_', '_interface_', '_interface_init_', '_interface_is_cached_', '_is_atomic', '_kash_', '_kash_init_', '_latex_', '_latex_coeff_repr', '_lcm', '_lmul_', '_macaulay2_', '_macaulay2_init_', '_magma_init_', '_maple_', '_maple_init_', '_mathematica_', '_mathematica_init_', '_mathml_', '_maxima_', '_maxima_init_', '_maxima_lib_', '_maxima_lib_init_', '_mod_', '_mpmath_', '_mul_', '_mul_parent', '_neg_', '_octave_', '_octave_init_', '_pari_', '_pari_divisors_small', '_pari_init_', '_polymake_', '_polymake_init_', '_pow_', '_pow_int', '_pow_naive', '_r_init_', '_reduction', '_repr_', '_richcmp_', '_rmul_', '_rpy_', '_sage_', '_sage_input_', '_set_parent', '_shift_helper', '_singular_', '_singular_init_', '_sub_', '_symbolic_', '_sympy_', '_test_category', '_test_eq', '_test_new', '_test_nonzero_equal', '_test_not_implemented_methods', '_test_pickling', '_tester', '_unicode_art_', '_valuation', '_xgcd', 'abs', 'additive_order', 'base_extend', 'base_ring', 'binary', 'binomial', 'bits', 'cartesian_product', 'category', 'ceil', 'class_number', 'conjugate', 'coprime_integers', 'crt', 'degree', 'denominator', 'digits', 'dist', 'divide_knowing_divisible_by', 'divides', 'divisors', 'dump', 'dumps', 'euclidean_degree', 'exact_log', 'exp', 'factor', 'factorial', 'floor', 'gamma', 'gcd', 'global_height', 'imag', 'inverse_mod', 'inverse_of_unit', 'is_idempotent', 'is_integer', 'is_integral', 'is_irreducible', 'is_nilpotent', 'is_norm', 'is_one', 'is_perfect_power', 'is_power_of', 'is_prime', 'is_prime_power', 'is_pseudoprime', 'is_pseudoprime_power', 'is_rational', 'is_square', 'is_squarefree', 'is_unit', 'is_zero', 'isqrt', 'jacobi', 'kronecker', 'lcm', 'leading_coefficient', 'list', 'log', 'mod', 'multifactorial', 'multiplicative_order', 'n', 'nbits', 'ndigits', 'next_prime', 'next_prime_power', 'next_probable_prime', 'nth_root', 'numerator', 'numerical_approx', 'odd_part', 'ord', 'order', 'ordinal_str', 'parent', 'perfect_power', 'popcount', 'powermod', 'powermodm_ui', 'powers', 'previous_prime', 'previous_prime_power', 'prime_divisors', 'prime_factors', 'prime_to_m_part', 'quo_rem', 'radical', 'rank', 'rational_reconstruction', 'real', 'rename', 'reset_name', 'round', 'save', 'sign', 'sqrt', 'sqrtrem', 'squarefree_part', 'str', 'subs', 'substitute', 'support', 'test_bit', 'trailing_zero_bits', 'trial_division', 'trunc', 'val_unit', 'valuation', 'xgcd']\n"}︡{"done":true}︡ ︠fbd16cf0-0843-4e27-b65a-4b19d28bfa24s︠ ### if you don't put restrictions on inputs ### weird things can happen q = fraction(2,0) print q p = fraction(3,0) print p print p == q ︡60f87fde-cebb-4c6c-a0f1-c30f33bfe116︡{"stdout":"2 / 0\n"}︡{"stdout":"3 / 0\n"}︡{"stdout":"True\n"}︡{"done":true}︡ ︠a7c1cba7-abfe-457b-a3aa-6b445e783a96ss︠ ### Raise Error to avoid bugs class fraction: def __init__(self,a,b): if b == 0: raise ValueError, "The divisor cannot be zero." self.numerator = a self.denominator = b self.gcd = gcd(a,b) def reciprocal(self): return fraction(self.denominator,self.numerator) def __repr__(self): return "{} / {}".format(self.numerator,self.denominator) def __add__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return fraction( a*d + b*c, b*d) def __eq__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator return a*d == b*c def __le__(self,other): a,b = self.numerator,self.denominator c,d = other.numerator,other.denominator if b*d < 0: return a*d >= b*c if b*d > 0: return a*d <= b*c q = fraction(2,0) print q ︡d85a2d7e-c3f0-42a6-a077-f6e0d7e67cbd︡{"stderr":"Error in lines 27-27\nTraceback (most recent call last):\n File \"/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py\", line 1188, in execute\n flags=compile_flags) in namespace, locals\n File \"\", line 1, in \n File \"\", line 4, in __init__\nValueError: The divisor cannot be zero.\n"}︡{"done":true}︡ ︠4a7efa9d-fa00-4069-875e-1182c673601f︠ ︡f79003dc-7496-4851-b670-a94353e8b64b︡ ︠9f20d4a5-6626-47fd-9308-d8da5f58503di︠ %md ## Project 1 Define a class called `D100` representing the poset $D_{100}$ and define the relation on it. Your class should be able to do ```Python D = [0] + [D100(k) for k in range(1,101)] ### [0] + make sure D[k] = D100(k) D[3] <= D[99] ``` and return `True`. Define each of `<`, `<=`, `>`, `>=`, `==` in your class. Your `__init__` function should raise an error when numbers not in 1,...,100. Bonus: Write a method `interval(self,other)` that returns all `x` with `self <= x <= other` as a list. ︡1491331a-ff0e-4231-ae95-9c18acf6be1f︡{"done":true,"md":"\n## Project 1\n\nDefine a class called `D100` representing the poset $D_{100}$ and define the relation on it. \nYour class should be able to do \n```Python\nD = [0] + [D100(k) for k in range(1,101)] \n### [0] + make sure D[k] = D100(k)\nD[3] <= D[99]\n```\nand return `True`. \nDefine each of `<`, `<=`, `>`, `>=`, `==` in your class.\nYour `__init__` function should raise an error when numbers not in 1,...,100. \nBonus: Write a method `interval(self,other)` that returns all `x` with `self <= x <= other` as a list."} ︠49a8da51-288f-4181-b23f-c90972e0f3f6s︠ class D100: ### Your answer here def __init__(self,n): if n not in list(range(1,101)): raise ValueError, "Input number should be in 1,...,100" self.value = n def __repr__(self): return str(self.value) def __le__(self,other): return other.value % self.value == 0 def __eq__(self,other): return self.value == other.value def __ne__(self,other): return not (self == other) def __lt__(self,other): return self <= other and self != other def __ge__(self,other): return other <= self def __gt__(self,other): return other < self def interval(self,other): return [D100(k) for k in range(self.value, other.value + 1) if self <= D100(k) and D100(k) <= other] ### test D = [0] + [D100(k) for k in range(1,101)] D[5] <= D[10] ︡d7c64285-ed1c-4f1d-ba56-f2f2d0dd26aa︡{"stdout":"True\n"}︡{"done":true}︡ ︠948c4818-f37f-4852-b6e6-2f9b15b0897ds︠ ### This should return error D100(101) ︡ee1b8def-af96-45f7-8fec-1984668a6f3a︡{"stderr":"Error in lines 1-1\nTraceback (most recent call last):\n File \"/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py\", line 1188, in execute\n flags=compile_flags) in namespace, locals\n File \"\", line 1, in \n File \"\", line 4, in __init__\nValueError: Input number should be in 1,...,100\n"}︡{"done":true}︡ ︠79a6164e-a407-4e0f-b3b7-36744d109b7bs︠ ### This should return error D100(0.5) ︡65c97518-b833-44d5-a309-6173453554eb︡{"stderr":"Error in lines 1-1\nTraceback (most recent call last):\n File \"/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py\", line 1188, in execute\n flags=compile_flags) in namespace, locals\n File \"\", line 1, in \n File \"\", line 4, in __init__\nValueError: Input number should be in 1,...,100\n"}︡{"done":true}︡ ︠8fc9da83-5576-4b73-af2a-3c694a798175s︠ ### interval ### expect [3, 9, 33, 99] D100.interval(D[3],D[99]) ︡9e776dea-eff6-4cf5-96e3-6b8aa04c3dac︡{"stdout":"[3, 9, 33, 99]\n"}︡{"done":true}︡ ︠1beb9d89-e5eb-4ea4-8b49-f779a357ee94︠