@@ -286,11 +286,242 @@ Python 使用关键字 class 定制自己的类,self 表示类实例对象本
286286
287287一个自定义类内包括属性、方法,其中有些方法是自带的。
288288
289+ ** 类(对象):**
289290
291+ ``` python
292+ class Dog (object ):
293+ pass
294+ ```
295+
296+ 以上定义一个 Dog 对象,它继承于根类 object,pass 表示没有自定义任何属性和方法。
297+
298+ 下面创建一个 Dog 类型的实例:
299+
300+ ``` python
301+ wangwang = Dog()
302+ ```
303+
304+ Dog 类现在没有定义任何方法,但是刚才说了,它会有自带的方法,使用 ` __dir__() ` 查看这些自带方法:
305+
306+ ``` python
307+ In [26 ]: wangwang.__dir__ ()
308+ Out[26 ]:
309+ [' __module__' ,
310+ ' __dict__' ,
311+ ' __weakref__' ,
312+ ' __doc__' ,
313+ ' __repr__' ,
314+ ' __hash__' ,
315+ ' __str__' ,
316+ ' __getattribute__' ,
317+ ' __setattr__' ,
318+ ' __delattr__' ,
319+ ' __lt__' ,
320+ ' __le__' ,
321+ ' __eq__' ,
322+ ' __ne__' ,
323+ ' __gt__' ,
324+ ' __ge__' ,
325+ ' __init__' ,
326+ ' __new__' ,
327+ ' __reduce_ex__' ,
328+ ' __reduce__' ,
329+ ' __subclasshook__' ,
330+ ' __init_subclass__' ,
331+ ' __format__' ,
332+ ' __sizeof__' ,
333+ ' __dir__' ,
334+ ' __class__' ]
335+ ```
336+
337+ 有些地方称以上方法为魔法方法,它们与创建类时自定义个性化行为有关。比如:
338+
339+ - ` __init__ ` 方法能定义一个带参数的类;
340+ - ` __new__ ` 方法自定义实例化类的行为;
341+ - ` __getattribute__ ` 方法自定义读取属性的行为;
342+ - ` __setattr__ ` 自定义赋值与修改属性时的行为。
343+
344+ ** 类的属性:**
345+
346+ ``` python
347+ def __init__ (self , name , dtype ):
348+ self .name = name
349+ self .dtype = dtype
350+ ```
351+
352+ 通过 ` __init__ ` ,定义 Dog 对象的两个属性:name、dtype。
353+
354+ ** 类的实例:**
355+
356+ ``` python
357+ wangwang = Dog(' wangwang' ,' cute_type' )
358+ ```
359+
360+ ` wangwang ` 是 ` Dog ` 类的实例。
361+
362+ ** 类的方法:**
363+
364+ ``` python
365+ def shout (self ):
366+ print (' I\' m %s , type: %s ' % (self .name, self .dtype))
367+ ```
368+
369+ ** 注意:**
370+
371+ - 自定义方法的第一个参数必须是 self,它指向实例本身,如 Dog 类型的实例 dog;
372+ - 引用属性时,必须前面添加 self,比如 ` self.name ` 等。
373+
374+ 总结以上代码:
375+
376+ ``` python
377+ In [40 ]: class Dog (object ):
378+ ... : def __init__ (self ,name ,dtype ):
379+ ... : self .name= name
380+ ... : self .dtype= dtype
381+ ... : def shout (self ):
382+ ... : print (' I\' m %s , type: %s ' % (self .name, self .dtype))
383+
384+ In [41 ]: wangwang = Dog(' wangwang' ,' cute_type' )
385+
386+ In [42 ]: wangwang.name
387+ Out[42 ]: ' wangwang'
388+
389+ In [43 ]: wangwang.dtype
390+ Out[43 ]: ' cute_type'
391+
392+ In [44 ]: wangwang.shout()
393+ I' m wangwang, type: cute_type
394+ ```
395+
396+ 看到创建的两个属性和一个方法都被暴露在外面,可被 wangwang 调用。这样的话,这些属性就会被任意修改:
397+
398+ ``` python
399+ In [49 ]: wangwang.name= ' wrong_name'
400+
401+ In [50 ]: wangwang.name
402+ Out[50 ]: ' wrong_name'
403+ ```
404+
405+ 如果想避免属性 name 被修改,可以将它变为私有变量。改动方法:属性前加 2 个 ` _ ` 后,变为私有属性。如:
406+
407+ ``` python
408+ In [51 ]: class Dog (object ):
409+ ... : def __init__ (self ,name ,dtype ):
410+ ... : self .__name= name
411+ ... : self .__dtype= dtype
412+ ... : def shout (self ):
413+ ... : print (' I\' m %s , type: %s ' % (self .name, self .dtype))
414+ ```
415+
416+ 同理,方法前加 2 个 ` _ ` 后,方法变为“私有方法”,只能在 Dog 类内被共享使用。
417+
418+ 但是这样改动后,属性 name 不能被访问了,也就无法得知 wangwang 的名字叫啥。不过,这个问题有一种简单的解决方法,直接新定义一个方法就行:
419+
420+ ``` python
421+ def get_name (self ):
422+ return self .__name
423+ ```
424+
425+ 综合代码:
426+
427+ ``` python
428+ In [52 ]: class Dog (object ):
429+ ... : def __init__ (self ,name ,dtype ):
430+ ... : self .__name= name
431+ ... : self .__dtype= dtype
432+ ... : def shout (self ):
433+ ... : print (' I\' m %s , type: %s ' % (self .name, self .dtype))
434+ ... : def get_name (self ):
435+ ... : return self .__name
436+ ... :
437+
438+ In [53 ]: wangwang = Dog(' wangwang' ,' cute_type' )
439+
440+ In [54 ]: wangwang.get_name()
441+ Out[54 ]: ' wangwang'
442+ ```
443+
444+ 但是,通过此机制,改变属性的可读性或可写性,怎么看都不太优雅!因为无形中增加一些冗余的方法,如 ` get_name ` 。
445+
446+ 下面,通过另一个例子,解释如何更优雅地改变某个属性为只读或只写。
447+
448+ 自定义一个最精简的 Book 类,它继承于系统的根类 object:
449+
450+ ``` python
451+ class Book (object ):
452+ def __init__ (self , name , sale ):
453+ self .__name = name
454+ self .__sale = sale
455+ ```
456+
457+ 使用 Python 自带的 property 类,就会优雅地将 name 变为只读的。
458+
459+ ``` python
460+ @ property
461+ def name (self ):
462+ return self .__name
463+ ```
464+
465+ 使用 @property 装饰后 name 变为属性,意味着 ` .name ` 就会返回这本书的名字,而不是通过 ` .name() ` 这种函数调用的方法。这样变为真正的属性后,可读性更好。
466+
467+ ``` python
468+ In [101 ]: class Book (object ):
469+ ... : def __init__ (self , name , sale ):
470+ ... : self .__name = name
471+ ... : self .__sale = sale
472+ ... : @ property
473+ ... : def name (self ):
474+ ... : return self .__name
475+
476+ In [102 ]: a_book = Book(' magic_book' ,100000 )
477+
478+ In [103 ]: a_book.name
479+ Out[103 ]: ' magic_book'
480+ ```
481+
482+ property 是 Python 自带的类,前三个参数都是函数类型。更加详细的讨论放在后面讨论装饰器时再展开。
483+
484+ ``` python
485+ In [104 ]: help (property )
486+ Help on class property in module builtins:
487+
488+ class property (object )
489+ | property (fget = None , fset = None , fdel = None , doc = None )
490+ ```
491+
492+ 如果使 name 既可读又可写,就再增加一个装饰器 `@name .setter ` 。
493+
494+ ```python
495+ In [105]: class Book (object ):
496+ ... : def __init__ (self , name , sale ):
497+ ... : self .__name = name
498+ ... : self .__sale = sale
499+ ... : @ property
500+ ... : def name (self ):
501+ ... : return self .__name
502+ ... : @ name.setter
503+ ... : def name (self ,new_name ):
504+ ... : self .__name = new_name
505+
506+ In [106 ]: a_book = Book(' magic_book' ,100000 )
507+
508+ In [107 ]: a_book.name = ' magic_book_2.0'
509+
510+ In [108 ]: a_book.name
511+ Out[108 ]: ' magic_book_2.0'
512+ ```
513+
514+ 注意这种装饰器写法:name.setter,name 已经被包装为 property 实例,调用实例上的 setter 函数再包装 name 后就会可写。对于 Python 入门者,可以暂时不用太纠结这部分理论,使用 Python 一段时间后,再回过头来自然就会理解。
515+
516+ ## 小结
290517
518+ 今天学习 Python 的四大基本数据类型。数值型 int、float 等;容器型 list、dict、tuple、set 等;字符型 str 与正则表达式介绍;自定义类的基本语法规则,class、属性和方法等。
291519
520+ ** 动画对应短视频下载链接:**
292521
522+ https://pan.baidu.com/s/1MrnrXEnl54XDYYwkZbSqSA
293523
524+ 提取码:634k
294525
295526
296527
0 commit comments