面向对象 - 封装、property装饰器、绑定方法*非绑定方法

一:封装

造对象、整合程序,就已经用到了封装的思想。

在封装的基础上,我可以将装到对象或者类中的属性给隐藏起来。

注意:
(1)在定义类或者初始化对象时,在属性前加__,就会将该属性隐藏起来但该隐藏起始只是一种变形_类名__属性名,并没有真的隐藏起来

(2)该变形操作是在类定义阶段扫描语法时发生的变形,类定义之后添加的__开头的属性不会发生变形

(3)该隐藏是对外 不对内的

(4) 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

 

1.将数据和功能的属性隐藏

class People:
    def __init__(self, name, age, gender):
        self.__name = name  # 通过加双下划线__的方法来隐藏属性名
        self.age = age
        self.gender = gender

    def __choose(self):  # obj._Student__choose
        print("%s 正在选课" % self.__name)


p1 = People('xxq', 18, 'male')  # 实例化对象p1,并且传值

# print(p1.name)
# AttributeError: 'People' object has no attribute 'name'
# 属性错误:'People'对象没有'name'属性

print(p1.age)
# 18

print(p1.gender)
# male

# print(p1.__choose())
# AttributeError: 'People' object has no attribute '__choose'
# 属性错误:'People'对象没有'__choose'属性

print(p1.__dict__)
# {'_People__name': 'xxq', 'age': 18, 'gender': 'male'}
# 此时,name属性名并未真正地被隐藏,而是进行了变形:_People(类名)__name(属性名)

print(p1._People__name)  # 依旧可以通过:p1(对象名)._People__name(变型后的属性名) 来访问
# xxq

print(p1._People__choose())  # 依旧可以通过:p1(对象名)._People__name(变型后的属性名) 来访问
# xxq 正在选课
 

2.将隐藏的属性通过接口调用

class People:
    def __init__(self, name, age, gender):
        self.__name = name  # 通过加双下划线__的方法来隐藏属性名
        self.age = age
        self.gender = gender

    def show_name(self):    # 虽然不能在外部直接调用,但是可以在类内部的函数调用,然后外部调用函数,间接访问
       print(self.__name)


p1 = People('xxq', 18, 'male')  # 实例化对象p1,并且传值

p1.show_name()
# xxq
 

3.隐藏属性的意义何在

把数据属性隐藏起来的意义是:在类内开放接口,让外界使用者通过接口来操作属性值,我们可以在接口之上附加任意的逻辑
来严格控制外界使用者对属性的操作

 

二:property装饰器

 

1.BMI(体质指数)例子

BMI指数(又称身体质量指数),是用体重公斤数除以身高米数平方得出的数字,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。用户可根据测试结果安排更加合理的膳食营养和锻炼。健康人生从此开始。

 

class People:

    def __init__(self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight

    def bmi(self):
        out_bmi = self.weight / (self.height ** 2)
        return (f'您的BMI指数为:{out_bmi}')


p = People('xxq', 1.8, 70)
print(p.bmi())

# 您的BMI指数为:21.604938271604937
在上述例子中,实例化了一个对象p,但是bmi其实是一个功能函数,但是最后输出的时候,是b.bmi(),而bmi则像是一个数据属性,不应该加括号。
此时,就需要一个property装饰器来把这个函数伪装成一个数据属性
class People:

    def __init__(self, name, height, weight):
        self.name = name
        self.height = height
        self.weight = weight

    @property
    def bmi(self):
        out_bmi = self.weight / (self.height ** 2)
        return (f'您的BMI指数为:{out_bmi}')


p = People('xxq', 1.8, 70)
print(p.bmi)

# 您的BMI指数为:21.604938271604937
 

例子:查、改、删

class People:
    def __init__(self, name, age, gender):
        self.name = name  # 通过加双下划线__的方法来隐藏属性名
        self.__age = age
        self.gender = gender

    @property
    def show_age(self):
        print(f'年龄:{self.__age}')

    def set_age(self, x):
        if type(x) is not int:
            print("年龄必须是整型,傻叉")
        else:
            self.__age = x
            print(f'修改成功,修改后年龄为:{self.__age}')

    @property
    def del_age(self):
        print('想啥呢,怎么可能让你删呢!')


p1 = People('xxq', 18, 'male')  # 实例化对象p1,并且传值

p1.show_age
# 年龄:18

p1.set_age(20)
# 修改成功,修改后年龄为:20

p1.del_age
# 想啥呢,怎么可能让你删呢!
 

进阶 - 完全伪装

class People:
    def __init__(self, name, age, gender):
        self.name = name  # 通过加双下划线__的方法来隐藏属性名
        self.__age = age
        self.gender = gender

    def show_age(self):
        print(f'年龄:{self.__age}')

    def set_age(self, x):
        if type(x) is not int:
            print("年龄必须是整型,傻叉")
        else:
            self.__age = x
            print(f'修改成功,修改后年龄为:{self.__age}')

    def del_age(self):
        del self.__age
        print('哟!删库跑路啊,等着坐牢吧!!!')

    age = property(show_age, set_age, del_age)


p1 = People('xxq', 18, 'male')  # 实例化对象p1,并且传值

p1.age
# 年龄:18

p1.age = 20
# 修改成功,修改后年龄为:20

del p1.age
# 哟!删库跑路啊,等着坐牢吧!!!
 

三:绑定方法 与 非绑定方法

 

1.绑定方法:谁来调用就会将谁当作第一个参数传入

1.绑定给对象的方法:类中定义的函数默认就是绑定给对象的方法,应该是由对象调用,会把对象当作第一个参数传入

2.绑定给的方法:在类中的函数上加一个装饰器@classmethod,该函数就绑定给类了,应该是由类来调用,会把类当作第一个参数传入

class People:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tell_info(self):
        print(f'姓名:{self.name},年龄:{self.age}')

    @classmethod    # 装饰类的装饰器
    def f1(cls):
        print(cls)

    @staticmethod   # 装饰静态方法的装饰器
    def f2(x, y, z):
        print(x, y, z)


p1 = People('xxq', 18)
p1.tell_info()
# 姓名:xxq,年龄:18

print(p1.tell_info)
# <bound method People.tell_info of <__main__.People object at 0x000002480E572A58>>

print(People.f1)
# <bound method People.f1 of <class '__main__.People'>>

People.f1()
# <class '__main__.People'>

print(p1.f2)
# <function People.f2 at 0x000001EB3FED2F28>

print(People.f2)
# <function People.f2 at 0x000001EB3FED2F28>

p1.f2(1, 2, 3)
# 1 2 3

People.f2(1, 2, 3)
# 1 2 3
 

2.非绑定方法:既不与类绑定也不与对象绑定,就是一个普通的函数,谁都可以来调用,没有自动传参的效果

在函数上添加装饰器@staticmethod

 

settings.py

IP = "127.0.0.1"
PORT = 3306
import uuid
import settings


class MySQL:
    def __init__(self, ip, port):
        self.mid = self.__create_id()
        self.ip = ip
        self.port = port

    def tell_info(self):
        print("%s:<%s:%s>" % (self.mid, self.ip, self.port))

    @staticmethod
    def __create_id():
        return uuid.uuid4()

    @classmethod
    def from_conf(cls):
        return cls(settings.IP, settings.PORT)


# obj = MySQL("10.10.11.11",3306)
# obj.tell_info()


obj1 = MySQL.from_conf()
obj1.tell_info()
# a62da398-6d2d-47b6-8105-ac2ca4d95828:<127.0.0.1:3306>
posted @ 2020-08-15 11:56  Οo白麒麟оΟ  阅读(136)  评论(0编辑  收藏  举报