python学习笔记整理(一)

  1 '''
  2 类和对象
  3 类其实就是模板,对象就是通过模板造出来的看得见摸得着的东西,
  4 如通过图纸造飞机,通过月饼模子印月饼。
  5 类Class的组成:
  6 1、类的名称:类名
  7 2、类的属性:一组数据,变量
  8 3、类的方法:进行操作的方法或行为
  9 如人类,身高年龄是人的属性,吃喝拉撒是行为
 10 
 11 
 12 '''
 13 
 14 class P:
 15     def eat(self):
 16         print("在吃东西。。。")
 17     def introduce(self):
 18         print("%s的年龄是:%s"%(self.name,self.age))
 19     def print_self(self):
 20         print(self)
 21 
 22 # 创建对象 
 23 tom = P() 
 24 # tom这个对象保存的是一串内存地址。
 25 print(tom) # <__main__.P object at 0x0000023433CFEB00>
 26 #调用对象里的方法
 27 tom.eat() 
 28 # python内存分析: https://zhuanlan.zhihu.com/p/59599988
 29 # 给对象添加属性
 30 tom.name = "汤姆"
 31 tom.age = 18
 32 tom.introduce()
 33 
 34 # 注意:
 35 # 在类中定义的方法默认是实例方法,该方法与普通的函数只有一个区别,那就是他们必须要
 36 # 有一个额外的第一参数,该参数保存的是类的实例化对象在计算机中的内存地址,通常被命名为self,也可以是其他名。
 37 # 没有self参数的话,调用方法时会报错:takes 0 positional arguments but 1 was given
 38 tom.print_self() #<__main__.P object at 0x000001D6BD4A1F28>
 39 # 相当于tom.introduce(tom)
 40 
 41 
 42 # __init__(self)方法
 43 # 初始化方法,当类中有init方法时,在创建类的对象的时候会python会自动调用
 44 # init方法,并把对象的引用(内存地址)传进去。在这个方法里面就可以直接初始化
 45 # 一些属性,而不用在外面去添加了。在创建对象的时候直接把属性值通过参数传进来
 46 
 47 
 48 class P1:
 49     def __init__(self,name,age):
 50         self.name = name
 51         self.age = age
 52 
 53     def __str__(self):
 54         return "哈哈哈"
 55     def introduce(self):
 56         print("%s的年龄是:%s"%(self.name,self.age))
 57     
 58 lyf = P1("刘亦菲",22)
 59 lyf.introduce() #刘亦菲的年龄是:22
 60 
 61 # __str__(self)方法
 62 # 当直接打印对象的时候,得到的是一个内存地址,当类中有str方法时,再去打印对象
 63 # 得到的是str方法中return的值。
 64 print(lyf) #哈哈哈
 65 
 66 # 延伸:以前多个函数可以共用一个全局变量,现在一个对象里面的多个方法可以共用一个属性,
 67 # 感觉对象就是把全局变量和函数打个包,多个对象就打多个包,直接互不影响。
 68 
 69 
 70 # 隐藏属性
 71 # 保护属性安全,即不能随意修改,一般处理方法为:1、将属性定义为私有属性;2、添加一个可调用的方法
 72 #  
 73 # 直接对属性赋值可能会出现在代码语法上没问题,但在逻辑上行不通的问题。例如年龄
 74 # 被错误的设置成222岁。可以在类里通过方法对传入的参数进行判断。
 75 
 76 class P2:
 77 
 78     def set_age(self,age):
 79         if age>0 and age<=100:
 80             self.age = age
 81         else:
 82             self.age = "年龄不合法"
 83 
 84     def get_age(self):
 85         return self.age
 86     
 87 lyf = P2()
 88 lyf.set_age(222)
 89 age = lyf.get_age()
 90 print(age) #年龄不合法
 91 
 92 
 93 #私有方法
 94 #当某个核心方法不想被外界直接调用,可以将此方法变为私有方法。再通过其他方法间接调用。
 95 class P3:
 96     # 私有属性
 97     def __init__(self,name,age):
 98         self.name = name
 99         self.__age = age
100     # 私有方法
101     def __get_money(self):
102         print('正在取钱')
103     # 公有方法
104     def get_money(self,password):
105         ''' 通过判断后决定是否调用私有方法'''
106         if password==123456: 
107             self.__get_money()
108             print(self.__age) #调用私有属性
109         else:
110             print("密码错误")
111 
112 lyf=P3("刘亦菲",22)
113 lyf.get_money(123) #密码错误
114 lyf.get_money(123456)  #正在取钱
115 print(lyf.name)  # 刘亦菲
116 # print(lyf.__age) 报错
117 
118 # __del__(self)方法
119 # 如果对象的引用计数变为0,就会自动调用__del__()方法
120 # getrefcount()方法可以查看引用计数
121 import sys
122 class P4:
123     def __del__(self):
124         print("over")
125 
126 p1 = P4()
127 p2 = p1
128 print(sys.getrefcount(p1))# 3,该方法本身有一个变量接收对象,所以引用计数多1
129 print(p1,p2)
130 # 此时对象的引用计数为2,p1p2保存的是同一个地址。
131 del p1
132 #删除p1,引用计数变为1,对象还存在
133 print(p2)
134 del p2
135 #删除p2,引用计数为0,对象在系统中被删除,内存释放,此时执行类里面的__del__()
136 print("这句话出现在over后面")
137 
138 
139 # 继承
140 # 类可以继承自另一个类,继承是一种创建新的类的方式,可以减少代码冗余、提高重用性
141 # 如果一个类没有继承任何类,则默认继承object类。
142 class Fu(object):
143     a=1
144     print("我是父类,我继承自基类")
145 #注意:类在定义的时候就执行类体代码,执行顺序是从上到下
146 class Zi(Fu):
147     def zi(self):
148         print("我是子类,我继承自父类")
149 
150 
151 class Sun(Zi):
152     def sun(self):
153         print("我是孙子类,我继承自子类")
154 sun = Sun()
155 print(sun.a) # 1
156 sun.zi() #我是子类,我继承自父类
157 
158 
159 # 重写
160 # 当子类出现了跟父类同名的属性和方法时,优先调用子类的
161 class Dog:
162     a=1
163     def eat(self):
164         print("吃骨头")
165 
166 class Uzi(Dog):
167     a=2
168     def eat(self):
169         print("uzi不吃骨头")
170         # Dog.eat(self)    
171 
172 uzi = Uzi()
173 uzi.eat()  #uzi不吃骨头
174 print(uzi.a) #2
175 # 如果非要调用Dog类的eat该怎么办呢?
176 # 调用被重写的方法:
177 # 1、类名.方法名(self)
178 # 2、super().方法名()
179 class Animal:
180     def eat(self):
181         print("吃东西")
182 
183 class Dog(Animal):
184     a=1
185     def eat(self):
186         print("吃骨头")
187 
188 class Uzi(Dog):
189     a=2
190     def eat(self):
191         print("uzi不吃骨头")
192         Dog.eat(self)
193         Animal.eat(self)
194         super().eat()    
195 uzi = Uzi()
196 uzi.eat()
197 
198 # 注意,用类名.方法名(self)有弊端,假如类名改了,那继承自它的所有类调用时都需要修改类名,
199 # 很麻烦。并且在多继承下还会出现重复调用的问题。这时候用super()就好了。
200 
201 
202 # 私有方法和属性的继承
203 class A:
204     def __init__(self):
205         self.num1 = 1
206         self.__num2 = 2
207     def test1(self):
208         print("test1")
209     def __test2(self):
210         print("test2")
211     def test3(self):
212         self.__test2()
213         print(self.__num2)
214 
215 
216 class B(A):
217     def test4(self):
218         self.__test2()
219         print(self.__num2)
220 
221 
222 b=B()
223 b.test3()
224 # b.test4()
225 # b.__test2()
226 
227 # 私有方法和属性不会被继承,子类中的方法不能调用父类的私有方法和私有属性,父类的方法
228 # 可以直接调用私有方法和私有属性。
229 
230 
231 
232 # 多继承
233 class Base(object):
234     def test(self):
235         print("base")
236 class A(Base):
237     def test(self):
238         print("A")
239 class B(Base):
240     def test(self):
241         print("B")
242 class C(object):
243     def test(self):
244         print("C")
245 class D(A,B,C):
246     def test(self):
247         print("D")
248 
249 d = D()
250 d.test() # D
251 print(D.__mro__) # 类名.__mro__ :查看调用方法的顺序
252 # (<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, 
253 # <class '__main__.Base'>, <class '__main__.C'>, <class 'object'>)
254 
255 
256 
257 
258 # 多态
259 # 多态是建立在继承和重写的基础上的。
260 # 面向对象三要素:封装继承多态
261 class A(object):
262     def print_self(self):
263         print("====A====")
264 
265 
266 class B(A):
267     def print_self(self):
268         print("====B====")
269 
270 class C(object):
271     def print_self(self):
272         print("====C====")
273 
274 def test(obj):
275     obj.print_self()
276 a=A()
277 b=B()
278 c=C()
279 test(a)
280 test(b)
281 test(c)
282 '''
283 定义test函数的时候并未声明传入的是什么类型的参数,不过只要传入的实例对象
284 里面有print_self方法即可,不管他是A类型还是A的子类B类型还是C类型。在真正调用
285 的时候才会确定实际的类型。这就是多态的体现。即见人说人话见鬼说鬼话。
286 注意:当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型
287 和Python自带的数据类型,比如str、list、dict没什么两样。
288 '''
289 print(type(a)) # <class '__main__.A'>
290 print(type(c)) # <class '__main__.C'>
291 
292 
293 
294 # 实例属性和类属性
295 class Dog(object):
296     a = 1
297     __b = 2
298     def __init__(self,name):
299         self.name = name
300 
301 
302 d=Dog("zw") # 创建实例对象
303 print(d.a) # 因为实例对象没有属性a,所以用到类对象的属性a
304 print(Dog.a) #直接调用类的属性
305 d.a = 18  # 给实例对象添加实例属性a
306 print(d.a) # 实例对象有属性a则不用类属性a
307 print(Dog.a) # 类属性a不变,还是1
308 Dog.a = 11  # 修改类属性
309 print(Dog.a) # 11
310 
311 '''
312 总结:
313 实例属性属于实例对象所有,各实例对象之间互不干扰;
314 类属性属于类对象所有,所有实例对象共享类属性;
315 取名时尽量避免实例属性和类属性重名。
316 '''
317 
318 # 类方法、实例方法、静态方法
319 
320 # 对类属性进行操作常用到类方法
321 # 为避免代码中函数和类并存的乱象,将普通函数转为静态方法放到类里面
322 
323 class Test(object):
324     num = 0
325     # 实例方法
326     def __init__(self):
327         pass
328 
329     # 类方法,加装饰器
330     @classmethod
331     def modify_num(cls):
332         cls.num+=100
333 
334     # 静态方法,加装饰器
335     @staticmethod
336     def sta():
337         print("hahahhahahah")
338 
339 t = Test()
340 # 直接通过类名调用类方法:
341 Test.modify_num() 
342 print(Test.num) # 100
343 # 通过类创建出来的对象调用类方法:
344 t.modify_num()
345 print(Test.num) # 200
346 
347 #调用静态方法:两者都行
348 Test.sta()
349 t.sta()
350 
351 
352 
353 # __new__(cls)方法
354 
355 class Test(object):
356     def __init__(self):
357         pass
358 
359     def __new__(cls): # 此处接收的实参为类对象的引用
360         return object.__new__(cls)
361         # 调用基类的new方法来创建实例对象
362 
363 print(id(Test))
364 t=Test()
365 print(id(t))
366 '''
367 程序从上往下:
368 1、先创建一个类对象,Test存引用;
369 2、执行 Test(),传入实参Test引用,调用__new__方法来创建实例对象,
370     返回实例对象的引用;
371 3、执行__init__方法,传入实例对象的引用;
372 
373 创建和初始化两个方法合起来相当于Java里面的构造方法。
374 '''
375 
376 # 单例
377 # 做到类的实例对象只创建一次
378 # 让类属性保存第一次创建的实例的引用,以后每次调用new方法都不会去创建新的实例,
379 # 而是返回第一次的实例
380 class Dog(object):
381     __instance = None
382     def __new__(cls):
383         if cls.__instance == None:
384             cls.__instance = object.__new__(cls)
385             return cls.__instance
386         else:
387             return cls.__instance
388 
389 a = Dog()
390 print(id(a))  #2884513002720
391 b = Dog()
392 print(id(b))  #2884513002720
393 
394 # 单例初始化
395 
396 class Dog(object):
397     __instance = None
398     def __new__(cls,name):
399         # 这个形参name别忘了,虽然用不到
400         if cls.__instance == None:
401             cls.__instance = object.__new__(cls)
402             return cls.__instance
403         else:
404             return cls.__instance
405     def __init__(self,name):
406         self.name = name
407 
408 a=Dog("张三")
409 print(a.name) #张三
410 b=Dog("李四")
411 print(b.name) #李四
412 print(a.name) #李四  每次初始化覆盖上次的实例属性的值
413 
414 # 只初始化一次
415 class Dog(object):
416     __instance = None
417     __init_flag = False
418     def __new__(cls,name):
419         # 这个形参name别忘了,虽然用不到
420         if cls.__instance == None:
421             cls.__instance = object.__new__(cls)
422             return cls.__instance
423         else:
424             return cls.__instance
425     def __init__(self,name):
426         if Dog.__init_flag == False:
427             self.name = name
428             Dog.__init_flag = True
429 
430 a=Dog("张三")
431 print(a.name) #张三
432 b=Dog("李四")
433 print(b.name) #张三
434 
435 
436 # 异常处理
437 try:
438     #这里输入有潜在异常的代码,要有针对性
439     1/0
440     print(wy)
441     
442 except(NameError,FileNotFoundError):
443     print("捕获到这两种异常后的处理操作。。。")
444 except Exception as err_message:
445     print("这里可捕获除上面两个之外的所有异常。。。")
446     print(err_message) # 输出原来的异常信息
447 else:
448     print("没有异常才会执行这个")
449 finally:
450     print("无论有没有异常都会执行finally")
451 
452 # 出现1/0的异常后立马执行Exception,然后finally,print(wy)不会执行。
453 # Exception是所有异常的基类
454 
455 # 异常传递
456 def test1():
457     print(haha)
458 
459 def test2():
460     try:
461         test1()
462     except Exception as a:
463         print("处理异常")
464         print(a)  # name 'haha' is not defined
465 
466 test2() 
467 
468 
469 # 自定义异常并抛出异常 
470 """
471 class InputException(Exception):
472     ''' 自定义异常类,继承自异常基类Exception'''
473     def __init__(self,age,max_age):
474         self.age = age
475         self.max_age = max_age
476 
477 class Test(object):
478     def __init__(self,switch): # 异常处理开关
479         self.switch = switch
480     def handle(self):
481         try:
482             age = input("请输入你的年龄:")
483             if int(age)>=120:
484                 # 创建自定义异常类的实例对象,传参,抛出自定义异常
485                 raise InputException(age,120) 
486 
487         except InputException as result: 
488             ''' 捕获异常,将实例对象的引用存入到变量result '''
489             if self.switch:
490                 print("InputException:输入的年龄%s不在合理范围之内,最大为%d"%(result.age,result.max_age))
491             else:
492                 print("异常捕获开关已关闭")
493 t1=Test(False)
494 t1.handle()
495 t2=Test(True)
496 t2.handle()
497 """
498 
499 '''
500 请输入你的年龄:150
501 异常捕获开关已关闭
502 请输入你的年龄:150
503 InputException:输入的年龄150不在合理范围之内,最大为120
504 '''
505 
506 # 模块
507 
508 '''
509 # 新建一个mod1.py文件,里面代码如下:
510 def test1():
511     print("这是mod1模块里的test1函数体")
512 
513 print(__name__)
514 if __name__ == "__main__":
515     test1()
516 
517 '''
518 import mod1   # 导入新建的模块
519 mod1.test1()
520 
521 # __name__方法:
522 # 当自己调用自己时,__name__ == "__main__";
523 # 当其他模块调用自己时,__name__ == "自己模块名"
524 
525 # 模块导入方式
526 
527 # 1、import 模块名   调用:模块名.函数名()
528 # 2、from 模块名 import 函数名  调用:函数名()
529 # 注意:from xxx import * ----此方式只能导入公有的属性、方法、类,
530 # 无法导入以单下划线开头(protected)或以双下划线开头(private)的属性、方法、类,
531 # 加了all变量可以实现非公有属性方法类的导入
532 
533 '''
534 # 模块 mod2.py
535 
536 __all__ = ['a','__a',"__test4",'_A']
537 
538 # public变量
539 a = 100
540 # protected变量
541 _a = 200
542 # private变量
543 __a = 300
544 
545 def test2():
546     print("这是mod2模块里的test2函数体")
547 def _test3():
548     print("这是mod2模块里的test3函数体")
549 def __test4():
550     print("这是mod2模块里的test4函数体")
551 
552 
553 class A:
554     def pri(self):
555         print("这是类A")
556 class _A:
557     def pri(self):
558         print("这是类_A")
559 class __A:
560     def pri(self):
561         print("这是类__A")
562 
563 '''
564 # __all__变量
565 # 模块里加入__all__变量,表示用from...import * 导入时只能导入all
566 # 里面保存的对象,防止导入不需要的东西。没有all则会导入所有公有的属性方法类
567 
568 
569 #
570 # 包:多个模块放在同一个文件夹下(其中包含初始化模块),则该文件夹就成了一个包。
571 # 在包的__init__.py模块里面的__all__变量还决定着包里的哪些模块可以被外界调用
572 '''
573 注意:多种导入方式的区别
574 1、用from packag import * 这种方式只能从包里面导入__init__.py中__all__变量
575 保存的模块,其他模块无法导入。
576 2、from packag import module,调用时用module.method()
577 3、可以用from packag.packag2.module import * 从包下面的指定模块里导入所有,
578 这种导入方式不需要在__init__.py中指定模块名。
579 4、import packag.module,调用时用packag.module.method()
580 
581 个人建议用第二种方式最好。
582 
583 个人建的包是无法在python交互式模式下导入的,若想在交互模式下使用,则应该构建发布模块。
584 具体的发布过程见另一篇博客:https://www.cnblogs.com/wangyi0419/p/12495814.html
585 '''
586 
587 
588 # 导入模块的搜索路径
589 # 在python中导入自己的模块时有时导不进来,可以在sys.path中添加自己模块的路径,这样
590 # python就能够找到了。
591 import sys
592 a = sys.path
593 print(a)
594 '''
595 [
596 'C:\develop\sublime2020\python_file', 
597 'C:\develop\devesoftware\python3.7\python37.zip', 
598 'C:\develop\devesoftware\python3.7\DLLs', 
599 'C:\develop\devesoftware\python3.7\lib', 
600 'C:\develop\devesoftware\python3.7', 
601 'C:\develop\devesoftware\python3.7\lib\site-packages'
602 ]'''
603 # sys.path.append("个人路径") 添加
604 
605 
606 # 列表生成式
607 # 
608 a=[i for i in range(2,8)]
609 print(a)
610 a=list(range(1,10))
611 print(a)
612 a=[i*j for i in range(1,5) for j in range(1,5)]
613 print(a)
614 
615 # 输出九九乘法表
616 print('
'.join([' '.join(['%s*%s=%-2s '%(j,i,j*i) for j in range(1,i+1)])for i in range(1,10)]))
617 
618 a = [i if i%2==0 else -i for i in range(1,11)]
619 print(a) #[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
620 a = [i  for i in range(1,11) if i%2==0 ]
621 print(a) #[2, 4, 6, 8, 10]
622 # 注意:
623 # 第一个if...else...是表达式,写在for前面;
624 # 写在for后面的if是过滤条件,不能带else
625 
626 
627 
628 # 字典生成式
629 cook_str='BIDUPSID=D0727533D7147B7;PSTM=1530348042;BAIDUID=B1005C9BC2EB28'
630 dic = {i.split('=')[0]:i.split('=')[1] for i in cook_str.split(";")}
631 print(dic) 
632 #{'BIDUPSID': 'D0727533D7147B7', 'PSTM': '1530348042', 'BAIDUID': 'B1005C9BC2EB28'}
633 
634 
635 
636 # 模块循环导入
637 # 在a模块中导入b模块,在b模块中又导入了a模块,这就是循环导入,陷入死循环了,无解。
638 # 在程序设计中要避免出现这种情况,设计上分层,降低耦合。
639 
640 
641 # 集合
642 # set,{},集合里的元素不会重复
643 a=[1,2,3,2,1]
644 # 怎么对列表a去重呢?
645 # 方法一
646 b=[]
647 for i in a:
648     if i not in b:
649         b.append(i)
650 print(b) # [1, 2, 3]
651 # 方法二
652 s = set(a)
653 print(s) # {1, 2, 3}
654 L = list(s)
655 print(L) # [1, 2, 3]
656 
657 
658 
659 # == 和is
660 # is 是比较两个引用是否指向了同一个对象(引用比较)。
661 # == 是比较两个对象是否相等。
662 a=1.1
663 b=1.1
664 print(a is b) # False
665 print(a==b) #  True
666 a=[1]
667 b=[1]
668 print(a is b) # False
669 print(a==b) # True
670 a=100
671 b=100
672 print(a is b) #  True
673 
674 # 为什么这个是true呢?到底哪些数字不会新建对象?
675 # 写个程序测一下:
676 a = 1
677 b = 1
678 while id(a) == id(b):
679     a+=1
680     b+=1
681 print(a-1) # 256
682 
683 a = 1
684 b = 1
685 while id(a) == id(b):
686     a-=1
687     b-=1
688 print(a+1) # -5
689 # 发现只有-5 到 256这之间的整数才不会新建对象,is的结果是true。
690 
691 a=555
692 b=555
693 print(a is b) # False
694 
695 
696 # 关于变量
697 '''
698 1、Python的变量创建过程是在代码第一次给他赋值就创建了变量,
699 之后的赋值会改变已经创建的变量名的值;
700 2、Python的变量是没有类型的,变量是通用的,只是在一个特定的时间点,
701 引用了一个特定的对象;
702 3、Python中 使用变量的时候,当变量出现在表达式中时,它会马上被所引用的对象所替代。
703 '''
704 
705 # 深拷贝和浅拷贝
706 import copy
707 a = [1,2,3]
708 b = [4,5,6]
709 c=[a,b]
710 d=c # 赋值,
711 e=copy.copy(c) # 浅拷贝,e和c指向不同内存,但是内部元素指向相同
712 f=copy.deepcopy(c) # 深拷贝,即递归拷贝,拷贝一切,f指向新的内存
713 a.append('haha')
714 print(c) # [[1, 2, 3, 'haha'], [4, 5, 6]]
715 print(e) # [[1, 2, 3, 'haha'], [4, 5, 6]]
716 print(f) # [[1, 2, 3], [4, 5, 6]]
717 print(id(c))
718 print(id(e))
719 print(id(f))# 三个不同的地址
720 
721 # 深浅拷贝是对于可变类型对象而言的,不可变类型对象在python中没有拷贝一说。
722 a = (1,2)
723 b = a
724 c = copy.copy(a)
725 d = copy.deepcopy(a)
726 print(id(a)) # 三个地址相同
727 print(id(c))
728 print(id(d))
729 
730 # 私有化
731 
732 # 给实例对象添加与私有属性同名的公有属性
733 class Test(object):
734     def __init__(self):
735         self.__a = 1
736         self.b=2
737     def get(self):
738         print(self.__a)
739         print(self.b)
740 t=Test()
741 t.__a = 10 
742 t.b=20
743 print(t.__a)
744 print(t.b)
745 t.get()
746 
747 
748 # property
749 # 正常情况下通过set设置私有属性的值,get来获取值,不让外界直接获取,同时设置的
750 # 时候也会对传入的实参进行必要的判断
751 class Goddess(object):
752     def __init__(self):
753         self.__age = 22
754     
755     def get_age(self):
756         return self.__age
757     def set_age(self,age):
758         if age>=30 or age<=18:
759             print("年龄不在合理区间内")
760         else:
761             self.__age = age
762             print("年龄已保存")
763 
764 g = Goddess()
765 print(g.get_age()) # 22
766 g.set_age(28) # 年龄已保存
767 print(g.get_age()) # 28
768 
769 
770 # 但这种做法每次都要调用set、get函数,稍微有点麻烦。可以通过property封装实现
771 # 像修改公有属性那样的用对象.属性名直接修改私有属性。
772 class Goddess(object):
773     def __init__(self):
774         self.__age = 22
775     
776     def get_age(self):
777         return self.__age
778     def set_age(self,age):
779         if age>=30 or age<=18:
780             print("年龄不在合理区间内")
781         else:
782             self.__age = age
783             print("年龄已保存")
784     age = property(get_age,set_age) # 这里的变量名age可以随意取
785 g = Goddess()
786 g.age = 25 # 相当于 g.set_age(25)
787 print(g.age) # 25 ,相当于 g.get_age()
788 
789 # property的第二种实现方式:装饰器
790 # 这里的set和get方法都要使用同一个名字age
791 # 
792 class Goddess(object):
793     def __init__(self):
794         self.__age = 22
795 
796     @property
797     def age(self):  
798         return self.__age
799 
800     @age.setter
801     def age(self,age):
802         if age>=30 or age<=18:
803             print("年龄不在合理区间内")
804         else:
805             self.__age = age
806             print("年龄已保存")
807 
808 g = Goddess()
809 g.age = 27 # 调用第一个age方法
810 print(g.age) # 27 调用第二个age方法
811 
812 # 元组的标志是逗号,而不是小括号。
原文地址:https://www.cnblogs.com/wangyi0419/p/12489068.html