Python学习笔记26:封装、@property、@staticmethod和@classmethod装饰器方法、反射getattr()

学习参考Eva-J女神姐姐的博客:https://www.cnblogs.com/Eva-J/,如有侵权,请联系删除!

封装

知识点整理:

# 会用到私有的这个概念de场景
#1.隐藏起一个属性 不想让类的外部调用
#2.我想保护这个属性,不想让属性随意被改变
#3.我想保护这个属性,不被子类继承

#私有后的属性,可以定义方法get_name实现调用
#私有后的属性,可以定义set_name实现修改
#父类的私有属性,不能被子类调用
#
# step1
# class Room:
#     def __init__(self,name,length,width):
#         self.name = name
#         self.__length = length
#         self.__width = width
#
#     def area(self):
#         return self.__length * self.__width
#
# jin = Room('金老板',2,1)
# print(jin.area())

# step2
# class Room:
#     def __init__(self,name,length,width):
#         self.__name = name
#         self.__length = length
#         self.__width = width
#
#     def area(self):
#         return self.__length * self.__width
#
#     def get_name(self):  # 私有后如何调用它
#         return self.__name
#
#     def set_name(self,newName): # 私有后还可以进行修改
#         if type(newName) is str and newName.isdigit() == False:
#             self.__name = newName
#         else:
#             print('不合法的姓名')
#
# jin = Room('金老板',2,1)
# print(jin.area())
# print(jin.get_name())
# jin.set_name('2')
# print(jin.get_name())

# step3
# 假设父类的私有属性,能被子类调用吗?不能
# class Foo:
#     __key = '123'   # _Foo__key
#
# class Son(Foo):
#     print(Foo.__key)  # _Son__key

  

@property装饰器

知识点整理:

# @property 用来对属性进行一些操作,如上面例子中的打折,那么这时候就可以把这个属性设置成
# 私有的,然后在调用@property来设置一个和属性同名的方法,在该方法中实现对属性的操作,且该方法的调用和类中属性的调用方式一样,属性的调用不用方法后面的括号
# 类中的属性值都是可以进行修改的,但是加入了@property装饰器的方法,不能进行修改,如果要进行修改,需要在加一个装饰器@属性_setter
# 本来类中不能加入同名字的方法,加入@name.setter后可以,还可以新增一个参数
# 如果要对属性进行删除,需先私有化,加上@property装饰器和@属性_deleter
# step1
# from math import pi
# class Circle:
#     def  __init__(self,r):
#         self.r = r
#
#     @property  # 把perimeter伪装为一个属性
#     def perimeter(self):
#         return  2*pi*self.r
#
#     @property  # 把area伪装为一个属性
#     def area(self):
#         return self.r**2*pi
#
# c1 = Circle(5)
# print(c1.area())  # 圆的面积应该是一个属性,但是却又是通过计算得到,如何把面积伪装为一个属性
# print(c1.perimeter())
# 加入装饰器后调用方式要改变
# print(c1.area)  # 属性的调用不用方法后面的括号
# print(c1.perimeter)


# step2
# 计算人的BMI指数
# class Person:
#     def __init__(self,name,high,weight):
#         self.name = name
#         self.high = high
#         self.weight = weight   # 此处是属性的赋值,不要参与计算
#
#     @property
#     def bmi(self):
#         return self.weight / self.high ** 2
#
# jin = Person('金老板',1.6,90)
# print(jin.bmi())
# print(jin.bmi) # 加入装饰器后调用方式和属性的调用方式相同
# 改名
# jin.name = '222' # 此处可以修改属性,
# print(jin.name)
# jin.bmi = 18  #不能修改加入了装饰器后面的方法
# jin.high = 1.8  # 可以修改属性
# print(jin.high)
# print(jin.bmi)

# step3
# class Person:
#     def __init__(self,name):
#         self.__name = name
#
#     @property  # 要用name.setter ,必须要先有property装饰器
#     def name(self):
#         return self.__name + 'sb'
#
#     @name.setter  # 本来类中不能加入同名字的方法,加入@name.setter后可以,还可以新增一个参数
#     def name(self,newname):
#         self.__name = newname
#
# tiger = Person('嗷嗷')
# print(tiger.name)  # 此时name不能在继续修改
# tiger.name = '欠缺'
# print(tiger.name)


# step4
# class Goods:
#     discount = 0.5
#     def __init__(self,name,price):
#         self.name = name
#         self.__price = price
#
#     @property
#     def price(self):
#         return self.__price * Goods.discount
#
# apple = Goods('苹果',5)
# print(apple.price)

# @property 用来对属性进行一些操作,如上面例子中的打折,那么这时候就可以把这个属性设置成
# 私有的,然后在调用@property来设置一个和属性同名的方法,在该方法中实现对属性的操作

# step5
# 属性可以查看、修改、删除
# class Person:
#     def __init__(self,name):
#         self.__name = name
#
#     @property  # 私有化一个属性方法
#     def name(self):
#         return self.__name
#
#     @name.deleter
#     def name(self):
#         del self.__name
#
# a = Person('aaa')
# print(a.name)
# del a.name
# print(a.name)

  

@stacticmethod和 @classmethod

知识点整理:

# 当这个方法的操作只设计静态属性的时候,就应该使用classmethod来装饰这个方法,这个方法就可以直接被类来直接调用
# 在完全面向对象的程序中,如果一个函数类还有对象都没关系,那么就用staticmethod将这个函数变成一个静态方法
# step1
# class Goods:
#     __discount = 0.8  # 手动改的方式修改成一个方法
#     def __init__(self,name,price):
#         self.name = name
#         self.__price = price
#
#     @property
#     def price(self):
#         return self.__price * Goods.__discount
#
#     @classmethod # 把下面的方法变成了类里面的方法,这个方法就直接可以被类调用,不需要依托任何对
#     def change_discount(cls,new_discount):
#         cls.__discount = new_discount
#
# a = Goods('苹果',5) # 如果不想先实例化,并且这个方法适用这个类中所有的情况,那么需要用到classmethod
# print(a.price)
# a.change_discount(0.5)
# print(a.price)
# 当这个方法的操作只设计静态属性的时候,就应该使用classmethod来装饰这个方法

# step2
# java
# class Login:
#     def __init__(self,name,password):
#         self.name = name
#         self.password = password
#
#     def login(self):pass
#
#     @staticmethod # 伪装成一个静态方法,这样这个方法和这个类和属性都没什么关系,不需要传默认的self
#     def get_usr_pwd():
#         usr = input('密码:')
#         pwd = input('账号:')
#         Login(usr,pwd)


# Login.get_usr_pwd() # 这样就可以直接调用这个方法了,且调用之前不需要实例化任何对象
# 在完全面向对象的程序中,如果一个函数类还有对象都没关系,那么就用staticmethod将这个函数变成一个静态方法

反射,getattr方法

知识点整理:

# 有一个字符串格式的名字存在命名空间里面,可以通过getattr拿到这个字符串的值
# 形式有类.属性、实例.方法
# hasattr和getattr是配套使用的,先判断有没有,没有也不报错,如果没有,没有就报错
# step1
# class Teacher:
#     dic = {'查看学生信息':'show_student','查看讲师信息':'show_teacher'}
#     def show_student(self):
#         print('show_student')
# 
#     def show_teacher(self):
#         print('show_teacher')
# 
#     @classmethod
#     def func(cls):
#         print('hahaha')

# hasattr, getattr, delattr
# ret = getattr(Teacher,'dic') # 字符串类型的数据类型,Teacher.dic,类.属性
# print(ret)
# 有一个字符串格式的名字存在命名空间里面,可以通过getattr拿到这个字符串的值

# ret1 = getattr(Teacher,'func')      # 类.方法
# print(ret1)   #  方法名,方法的内存地址
# ret1()        # 函数的内存地址加括号,就执行该方法

# if hasattr(Teacher,'dic1'):     # getattr是配套使用的,先判断有没有,没有也不报错,如果没有hasattr,没有就报错
#     ret = getattr(Teacher,'dic1')
#
# aa = Teacher()
# a_func = getattr(aa, 'show_teacher') # 这样拿到的是函数的内存地址
# a_func()

# alex = Teacher()
# for k in Teacher.dic:
#     print(k)
# 
# key = input('输入需求:')
# if hasattr(alex, Teacher.dic[key]):
#     func = getattr(alex, Teacher.dic[key])
#     func()

  皑皑

实现计算机作业:

import re

# step2 提取括号里面没有其他括号的表达式
# findall 会找出来所有符合条件的,但是对于3*5*6 + 2*3,匹配乘法的化,上面这种情况会出现漏
def dealwith(express):
    '''
    将表达式中的符号替换,+- 替换为-,-,-替换为+
    :return:
    '''
    express = express.replace('+-','-')
    express = express.replace('--','+')
    return express

def cal_express_son(exp_son):
    '''
    只用来计算最小型的两个数的乘除法
    :return:
    '''
    if '/' in exp_son:
        a,b = exp_son.split('/')
        return str(float(a) / float(b))
    elif '*' in exp_son:
        a,b  = exp_son.split('*')
        return str(float(a)* float(b))


def cal_express_no_bracket(exp):
    '''
    计算没有括号的表达式
    exp:没有经过处理的最内层带括号的表达式
    :return:
    '''
    exp = exp.strip('()')
    # print(exp)
    # 先乘除后加减,找第一个出现的乘法或除法
    while 1:
        ret = re.search('d+.?d*[*/]-?d+.?d*',exp)
        if ret:  # 说明表达式中还有乘除法
            exp_son =  ret.group()  # 子表达式,最简单的乘除法
            print(exp_son)
            ret = cal_express_son(exp_son)
            exp =  exp.replace(exp_son,ret)
            exp = dealwith(exp)
        else:  # 说明表达式中没有乘除了
            ret = re.findall('-?d+.d*',exp)
            # print('***',ret)
            sum = 0
            for i in ret:
                sum += float(i)
            return str(sum)

def remove_bracket(new_express):
    while 1:
        ret = re.search('([^()]+)',new_express)
        if ret:
            express_no_bracket = ret.group() # 表达式没括号
            print('匹配到内部不在有括号的值',express_no_bracket)
            ret = cal_express_no_bracket(express_no_bracket)
            # print(new_express,express_no_bracket,ret)
            new_express = new_express.replace(express_no_bracket,ret)
            new_express = dealwith(new_express)
            print(new_express)
        else:
            print('表达式中已经没有括号了:',new_express)
            ret = cal_express_no_bracket(new_express)
            # print(ret)
            return ret
            break

express = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
# step1 去空格
new_express = express.replace('  ','')
res = remove_bracket(new_express)
print(res)

  

原文地址:https://www.cnblogs.com/zheng1076/p/11097551.html