Python进阶-XVIII 封装、(属性、静态方法、类方法)语法糖、反射

1、封装

  类中的私有化:属性的私有化和方法的私有化

 

 会用到私有的这个概念de场景
  1.隐藏起一个属性 不想让类的外部调用
  2.我想保护这个属性,不想让属性随意被改变
   3.我想保护这个属性,不被子类继承
 1 class Room:
 2     """房间类"""
 3 
 4     def __init__(self, name, length, width, height):
 5         self.__name = name
 6         self.__length = length
 7         self.__width = width
 8         self.__height = height
 9 
10     def get_name(self):
11         return self.__name
12 
13     def set_name(self, new_name):
14         if type(new_name) is str and new_name.isdigit() == False:  # 新名称是字符串且不能是数字
15             self.__name = new_name
16 
17     def area(self):
18         return self.__length * self.__width
19 
20     def volume(self):
21         return self.__length * self.__width * self.__height
22 
23 
24 room = Room('标准间', 3.6, 3.0, 3.2)
25 
26 print(room.get_name())
27 room.set_name('豪华间')
28 print(room.get_name())
29 
30 print(room.area())
31 print(room.volume())
32 
33 
34 # 子类无法继承父类中的私有属性和私有方法
35 
36 
37 class Foo:
38     __key = '123'       # _Foo__key
39 
40 
41 class Son(Foo):
42     print(Foo.__key)     # _Son__key
43 
44 
45 son = Son()
46 # son.__key # AttributeError: type object 'Foo' has no attribute '_Son__key'
View Code

 

2、属性方法

  @property语法糖的使用场景

  如果方法不得不使用名词,而规矩是名词是属性,动词是方法。而使用名词是将运算后的值给它。

 1 class Room:
 2     """房间类"""
 3 
 4     def __init__(self, name, length, width, height):
 5         self.__name = name
 6         self.__length = length
 7         self.__width = width
 8         self.__height = height
 9 
10     def get_name(self):
11         return self.__name
12 
13     def set_name(self, new_name):
14         if type(new_name) is str and new_name.isdigit() == False:  # 新名称是字符串且不能是数字
15             self.__name = new_name
16 
17     @property
18     def area(self):  # 名词一般是属性,动词才是方法,为了解决有了属性语法糖
19         return self.__length * self.__width
20 
21     @property
22     def volume(self):
23         return self.__length * self.__width * self.__height
24 
25 
26 room = Room('标准间', 3.6, 3.0, 3.2)
27 print(room.volume)  # 有了@property可以像调用属性一样调用方法
28 print(room.area)
View Code
 属性的 查看 修改 删除
 1 class Person:
 2     def __init__(self, name):
 3         self.__name = name
 4 
 5     @property
 6     def name(self):
 7         return self.__name
 8 
 9     @name.setter   # 修改
10     def name(self, new_name):
11         self.__name = new_name
12 
13     @name.deleter    # 删除
14     def name(self):
15         del self.__name
16 
17 
18 tom = Person('Tom')
19 print(tom.name)
20 tom.name = 'Jone'
21 print(tom.name)
22 del tom.name  # 删除 有了@name.deleter才有效果
23 # print(tom.name)              # AttributeError: 'Person' object has no attribute '_Person__name'
View Code

 

3、静态方法和类方法

  method 方法
  staticmathod 静态的方法 ***
  classmethod 类方法 ****
  类的操作行为

  1)staticmethod  静态的方法

 1 class Login:
 2     def __init__(self, name, pwd):
 3         self.name = name
 4         self.__password = pwd
 5 
 6     def login(self):pass
 7 
 8     @staticmethod  # 该语法糖是声明该方法为静态方法
 9     def get_usr_pwd():
10         usr = input('请输入登录名:》》》').strip()
11         pwd = input('请输入密码:》》》').strip()
12         Login(usr, pwd)
13 
14 
15 Login.get_usr_pwd()

静态方法的应用场景:在完全面向对象的程序中,如果一个函数,既跟对象没有关系,
也跟类没有关系 那么就用staticmethod将这个函数变成一个静态方法

  2)classmethod 类方法

 1 class Goods:
 2     """商品类"""
 3     discount_rate = 0.5
 4 
 5     def __init__(self, name, price):
 6         self.name = name
 7         self.__price = price
 8 
 9     @property
10     def price(self):
11         return self.__price * Goods.discount_rate
12 
13     @classmethod  # 把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象
14     def change_discount_rate(cls, new_rate):
15         cls.discount_rate = new_rate
16 
17 
18 apple = Goods('apple', 9.8)
19 print(apple.price)
20 # apple.change_discount_rate(0.75) 如此调用合理,商品的折扣率是类的事,不应该由实例来控制!
21 Goods.change_discount_rate(0.8)
22 print(apple.price)

类方法的应用场景:
当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法

 

  3)、小结

  类方法和静态方法 都是类调用的
  对象可以调用类方法和静态方法么? 可以 一般情况下 推荐用类名调用
  类方法 有一个默认参数 cls 代表这个类 cls
  静态方法 没有默认的参数 就象函数一样

 

 

4、反射

  (1)、简介

  有此使用场景,知道一个类中的方法名的字符串形式,如何调用该方法?

  通过反射
  对象名 获取对象属性 和 普通方法
  类名 获取静态属性 和类方法 和 静态方法

  普通方法 self
  静态方法 @staticmethod
  类方法 @classmethod
  属性方法 @property

 

 (2)、反射的使用场景

 1 class Dog:
 2     fur = 'golden'
 3     def __init__(self, name, kind):
 4         self.name = name
 5         self.kind = kind
 6 
 7     def bite(self):
 8         print(self.name + "is biting!")
 9 
10     def walk(self):
11         print(self.name + "is walking!"

 

    1)反射对象

1 dog = Dog('duck','harsci')
2 
3 #   1)、反射对象的属性
4 if hasattr(dog, 'fur'):
5     print(getattr(dog, 'fur'))
6 
7 #   2)、反射对象的方法
8 if hasattr(dog, 'bite'):
9     getattr(dog, 'bite')()

 

    2)反射类

 1 class A:
 2     year = 2020
 3     @classmethod
 4     def get_year(cls):
 5         print(cls.year)
 6 # 1)获得类的属性
 7 A.year
 8 if hasattr(A, 'year'):
 9     print(getattr(A, 'year'))
10 # 2)获得类的方法
11 if hasattr(A, 'get_year'):
12     getattr(A, 'get_year')() # 如果不加classmethod装饰器,会报错get_year() missing 1 required positional argument: 'self'

 

    3)反射导入的模块

 1 import time
 2 
 3 t = ''
 4 if hasattr(time, 'time'):
 5     t = getattr(time, 'time')()  # 得到当前的时间的时间戳
 6     print(t)
 7 
 8 t = time.localtime(t)  # 将时间戳转化为结构时间
 9 
10 if hasattr(time, 'asctime'):
11     print(getattr(time, 'asctime')(t))  # asctime必须传结构时间

 

    4)反射自身(坐在的模块)

 1 import sys
 2 # 查看系统中所有模块
 3 print(sys.modules)
 4 # 找到本模块对应的key
 5 # '__main__': < module'__main__'from' D:/python_bases/day27/2_反射进阶.py' >
 6 
 7 # 1)、获得本模块的属性
 8 print(getattr(sys.modules["__main__"], 'dog').fur)
 9 
10 def get_year():
11     print(time.asctime(time.localtime(time.time())))
12 # 2)、获得本模块的方法
13 getattr(sys.modules['__main__'], 'get_year')()
14 
15 # 如果别的模块引入该模块,会无法执行,因为写死了'__main__',要改为变量
16 __main__ = '__main__'

(3)、反射的剩余方法:

 1 method_str = ['bite', 'walk']
 2 
 3 dog = Dog('金毛', '狮子狗')
 4 
 5 if hasattr(Dog, 'bite'):  # 内置函数一
 6     bite = getattr(Dog, method_str[0])  # 内置函数二
 7 
 8 bite(dog)
 9 setattr(Dog, 'price', 999) # 内置函数三
10 print(dog.price)
11 
12 delattr(Dog, 'price') # 内置函数四

你可能感兴趣的:(Python进阶-XVIII 封装、(属性、静态方法、类方法)语法糖、反射)