Python 面向对象编程
1 # -*- coding: utf-8 -*- 2 # 创建学生类 3 class Student(object): 4 5 def __init__(self, name, score): 6 self.__name = name 7 self.__score = score 8 def print_score(self): 9 print('%s:%s' % (self.__name, self.__score)) 10 11 def get_grade(self): 12 if self.__score >= 90: 13 return 'A' 14 elif self.__score >= 60: 15 return 'B' 16 else: 17 return 'C' 18 19 def set_score(self, score): 20 self.score = score 21 def get_score(self): 22 return self.__score 23 24 # def run(self): 25 # print('student is running...') 26 27 bart = Student('liuepgnfei', 99) 28 ''' 29 bart.print_score() 30 print(bart.get_grade()) 31 32 #bart.set_score(22) 33 #bart.print_score() 34 35 #print(bart.name) 36 #print(bart.score) 37 #print(Student) 38 39 #实际上是新增了一个__name变量 40 bart.__score = 88 41 print(bart.__score) 42 bart.print_score() 43 ''' 44 45 #继承与多态 46 class Animal(object): 47 def run(self): 48 print('Animal is running...') 49 50 class Dog(Animal): 51 52 def run(self): 53 print('Dog is running..') 54 def eat(self): 55 print('Eating meat...') 56 57 class Cat(Animal): 58 59 def run(self): 60 print('Cat is running..') 61 62 dog = Dog() 63 cat = Cat() 64 ''' 65 dog.run() 66 cat.run() 67 68 print(isinstance(dog, Animal)) 69 print(isinstance(dog, Dog)) 70 71 72 #传入一个student类也可以,只要有run()实现就行 73 def run_twice(a): 74 a.run() 75 a.run() 76 77 run_twice(dog) 78 --------------------------------------------- 79 80 #获取对象信息 81 str = 'love' 82 print(type(str)) 83 print(type(dog)) 84 85 import types 86 def fn(): 87 pass 88 89 print(type(fn)) 90 print(types.FunctionType) 91 print(types.BuiltinFunctionType) 92 print(types.LambdaType) 93 print(types.GeneratorType) 94 95 print(isinstance(dog, Dog)) 96 print(isinstance('a', str)) 97 98 print(dir('ABC')) 99 print(dir('ABC').__len__()) 100 print('ABC'.__len__()) 101 102 103 class MyObject(object): 104 def __init__(self): 105 self.__x = 9 106 def power(self): 107 return self.__x * self.__x 108 obj = MyObject() 109 110 print(hasattr(obj,'x')) 111 print(hasattr(obj,'y')) 112 print(setattr(obj,'y', 19)) 113 print(getattr(obj,'y')) 114 115 print(obj.y)#?? 116 117 fn = getattr(obj, 'power') 118 print(fn) 119 print(fn()) 120 121 class Student(object): 122 count = 0 123 124 def __init__(self, name): 125 self.name = name 126 Student.count += 1 127 128 print(Student("lilei").count) 129 print(Student("lilei").count) 130 print(Student("lilei").count) 131 print(Student("lilei").count) 132 ''' 133 134 ######### 135 #面向对象高级编程 136 ######### 137 138 #1、使用__slots__ 139 ''' 140 class Student(object): 141 pass 142 143 s=Student() 144 s.name = "Mike" 145 print(s.name) 146 147 def set_age(self, age): 148 self.age=age 149 150 #为对象绑定方法 151 from types import MethodType 152 s.set_age = MethodType(set_age, s) 153 s.set_age(25) 154 print(s.age) 155 156 #s2.set_age(20) 157 158 #为类绑定方法 159 def set_score(self, score): 160 self.score = score 161 162 #此时可理解绑定方法时,对应的绑定了score属性 163 Student.set_score = set_score 164 165 s2 = Student() 166 s2.set_score(100) 167 print(s2.score) 168 ''' 169 ''' 170 方法的绑定存在作用域的限制,类似于c语言中变量作用域 171 需要说明的是,即使绑定了方法,如果没有通过实例调用, 172 被绑定方法中的属性仍然未绑定至类对象中 173 ''' 174 ''' 175 class Student(object): 176 __slots__ = ('name', 'age') 177 178 s = Student() 179 s.name = 'Mike' 180 s.age = 20 181 print(s.age) 182 183 #子类中定义__slots__,以继承父类中的属性限制 184 class stu(Student): 185 __slots__ = ('score') 186 187 s2 = stu() 188 189 s2.age = 2 190 print(s2.age) 191 s2.score = 20 192 print(s2.score) 193 ''' 194 195 ''' 196 class Student(object): 197 def get_score(self): 198 return self._score 199 200 def set_score(self, value): 201 if not isinstance(value, int): 202 raise ValueError('score must be an intrger!') 203 if not (0 <= value <= 100): 204 raise ValueError('score must between 0~100!') 205 self._score = value 206 207 s = Student() 208 s.set_score(100) 209 #s.set_score(1000) 210 ''' 211 ''' 212 #使用装饰器 213 class Student(object): 214 215 #property:python内置装饰器,把一个方法变成属性调用 216 @property 217 def score(self): 218 print("getter()") 219 return self._score 220 221 #定义setter属性 222 @score.setter 223 def score(self, value): 224 if not isinstance(value, int): 225 raise ValueError('score must be an integer!') 226 if not (0 <= value <= 100): 227 raise ValueError('score must between 0~100!') 228 self._score = value 229 print("setter()") 230 231 s=Student() 232 233 import sys 234 print(sys._getframe().f_lineno) 235 #类似于方法绑定,只有调用setter绑定后,才存在width属性 236 #只定义@property,意味着width的getter成为类的属性,而只有定义了setter, 237 #并调用后,_width才成为类的属性 238 s.score = 60 239 240 print(sys._getframe().f_lineno) 241 s.score 242 243 244 class Screen(object): 245 @property 246 def width(self): 247 return self._width 248 @width.setter 249 def width(self, value): 250 self._width = value 251 252 @property 253 def height(self): 254 return self._height 255 @height.setter 256 def height(self, value): 257 self._height = value 258 259 @property 260 def resolution(self): 261 return self._height*self._width 262 263 s = Screen() 264 s.width = 1024 265 s.height = 768 266 print('resolution =', s.resolution) 267 if s.resolution == 786432: 268 print('测试通过!') 269 else: 270 print('测试失败!') 271 272 ''' 273 ''' 274 #3、多重继承 275 276 class Animal(object): 277 pass 278 279 class Mammal(object): 280 pass 281 282 class Runnable(object): 283 def run(self): 284 print('Running...') 285 286 class Flyable(object): 287 def fly(self): 288 print('Flying...') 289 290 #Dog多重继承了Mammal、Runnable 291 class Dog(Mammal, Runnable): 292 pass 293 class Bat(Mammal, Flyable): 294 pass 295 ''' 296 #MixIn 297 #python中会对多继承的类名后面添加MixIn,例如RunnableMinIn. 298 #这并不影响功能,但是会告诉读代码的人,这个类是一个MinIn类, 299 #该类是作为功能添加到子类中,并不是父类,作用等同于java中的interface 300 301 ''' 302 #4、定制类 303 #__str__():返回用户看到的字符串 304 #__repr__():返回开发者看到的字符串 305 class Student(object): 306 def __init__(self, name): 307 self.name = name 308 def __str__(self): 309 return 'Student object (name:%s)' % self.name 310 __repr__ = __str__ 311 312 print(Student("Mike")) 313 314 s = Student('Jane') 315 #命令行模式下直接执行s 316 s 317 ''' 318 319 #__iter__:该方法返回一个迭代对象,然后,Python的for循环就会不断 320 #调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到 321 #StopIteration错误时退出循环。 322 #说明:首次调用执行__iter__(),随后调用执行__next__() 323 324 #__getitem__:该方法可以使实例像list那样取第n个元素 325 #__setitem__:把对象视作list或dict来对集合复制 326 #__delitem__:用于删除某个元素 327 ''' 328 class Fib(object): 329 def __init__(self): 330 self.a, self.b = 0, 1 331 def __iter__(self): 332 return self 333 def __next__(self): 334 self.a, self.b = self.b, self.a + self.b 335 if self.a > 100000: 336 raise StopIteration() 337 return self.a 338 339 def __getitem__(self, n): 340 if isinstance(n, int):#n是索引 341 a, b = 1, 1 342 for x in range(n): 343 a, b = b, a+b 344 return a 345 346 if isinstance(n, slice):#n是切片 347 start = n.start 348 stop = n.stop 349 if start is None: 350 start = 0 351 a, b = 1, 1 352 L = [] 353 for x in range(stop): 354 if x >= start: 355 L.append(a) 356 a, b = b, a + b 357 return L 358 359 for n in Fib(): 360 print(n) 361 362 363 f = Fib() 364 print(f[0]) 365 print(f[1]) 366 print(f[2]) 367 print(f[3]) 368 369 #切片 370 print(f[:100]) 371 ''' 372 ''' 373 #__getattr__:动态返回一个属性;当不存在attr属性时,才会调用__getattr__() 374 #当__getattr__()也不存在时,默认返回None 375 class Student(object): 376 def __init__(self): 377 self.name = 'Mike' 378 379 def __getattr__(self, attr): 380 if attr == 'score': 381 return 99 382 raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr) 383 384 s=Student() 385 print(s.abc) 386 387 388 class Chain(object): 389 def __init__(self, path=''): 390 self._path = path 391 def __getattr__(self, path): 392 # return Chain('%s' % (self._path)) 393 # return Chain('%s' % (path)) 394 return Chain('%s/%s' % (self._path, path)) 395 def __str__(self): 396 return self._path 397 398 print(Chain().status.user.timeline.list) 399 400 #__call__:直接在实例本身上调用实例方法 401 class Student(object): 402 def __init__(self, name): 403 self.name = name 404 def __call__(self): 405 print("My name is %s." % self.name) 406 407 s = Student('Mike') 408 s() 409 410 #通过callable()函数,可以半段一个对象是否是‘可调用’对象 411 print(callable(Student)) 412 ''' 413 #更多的定制方法见python官方文档 414 #https://docs.python.org/3/reference/datamodel.html#special-method-names 415 416 #4、使用枚举类 417 #from enum import Enum, unique 418 #Month类型的枚举类 419 ''' 420 Month = Enum('Month', ('Jan', 'Feb', 'Mar')) 421 for name, member in Month.__members__.items(): 422 # print(name, '=>', member, ',', member.value) 423 print(member) 424 print(member.name) 425 print(member.value) 426 ''' 427 ''' 428 @unique #此装饰器可帮助我们检查保证没有重复值 429 class Weekday(Enum): 430 Sun = 0 431 Mon = 1 432 Tue = 2 433 Wed = 3 434 Thu = 4 435 Fri = 5 436 Sat = 6 437 438 day1 = Weekday.Mon 439 print(day1) 440 print(Weekday.Tue) 441 print(Weekday.Wed.value) 442 443 for name, member in Weekday.__members__.items(): 444 print(name, '=>', member) 445 446 class Gender(Enum): 447 Male = 0 448 Female = 1 449 450 class Student(object): 451 def __init__(self, name, gender): 452 self.name = name 453 self.gender = gender 454 455 bart = Student('Bart', Gender.Male) 456 if bart.gender == Gender.Male: 457 print('测试通过!') 458 else: 459 print('测试失败!') 460 ''' 461 #5、使用元类 462 ''' 463 class Hello(object): 464 def hello(self, name='world'): 465 print("Hello, %s." % name) 466 467 from hello import Hello 468 h=Hello() 469 h.hello() 470 471 #使用type()动态创建类 472 def fn(self, name='world'): 473 print('Hello, %s.' % name) 474 475 Hello = type('Hello', (object,), dict(hello=fn)) 476 h=Hello() 477 h.hello() 478 print(type(Hello)) 479 print(type(h)) 480 481 482 class ListMetaclass(type): 483 def __new__(cls, name, bases, attrs): 484 attrs['add'] = lambda self, value:self.append(value) 485 return type.__new__(cls, name, bases, attrs) 486 487 class MyList(list, metaclass=ListMetaclass): 488 pass 489 490 L = MyList() 491 L.add(1) 492 print(L) 493 ''' 494 495 class Field(object): 496 497 def __init__(self, name, column_type): 498 self.name = name 499 self.column_type = column_type 500 501 def __str__(self): 502 return '<%s:%s>' % (self.__class__.__name__, self.name) 503 504 505 class StringField(Field): 506 507 def __init__(self, name): 508 super(StringField, self).__init__(name, 'varchar(100)') 509 510 class IntegerField(Field): 511 512 def __init__(self, name): 513 super(IntegerField, self).__init__(name, 'bigint') 514 515 class ModelMetaclass(type): 516 517 def __new__(cls, name, bases, attrs): 518 if name=='Model': 519 return type.__new__(cls, name, bases, attrs) 520 print('Found model: %s' % name) 521 mappings = dict() 522 for k, v in attrs.items(): 523 if isinstance(v, Field): 524 print('Found mapping: %s ==> %s' % (k, v)) 525 mappings[k] = v 526 for k in mappings.keys(): 527 attrs.pop(k) 528 attrs['__mappings__'] = mappings # 保存属性和列的映射关系 529 attrs['__table__'] = name # 假设表名和类名一致 530 return type.__new__(cls, name, bases, attrs) 531 532 class Model(dict, metaclass=ModelMetaclass): 533 534 def __init__(self, **kw): 535 super(Model, self).__init__(**kw) 536 537 def __getattr__(self, key): 538 try: 539 return self[key] 540 except KeyError: 541 raise AttributeError(r"'Model' object has no attribute '%s'" % key) 542 543 def __setattr__(self, key, value): 544 self[key] = value 545 546 def save(self): 547 fields = [] 548 params = [] 549 args = [] 550 for k, v in self.__mappings__.items(): 551 fields.append(v.name) 552 params.append('?') 553 args.append(getattr(self, k, None)) 554 sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) 555 print('SQL: %s' % sql) 556 print('ARGS: %s' % str(args)) 557 558 class User(Model): 559 # 定义类的属性到列的映射: 560 id = IntegerField('id') 561 name = StringField('username') 562 email = StringField('email') 563 password = StringField('password') 564 565 u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') 566 u.save()