zoukankan      html  css  js  c++  java
  • 面向对象

    一:封装

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

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

    注意:
    (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>
    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    Singleton模式
    Factory模式
    AbstactFactory模式
    Maven的介绍及使用
    MySQL索引分析及使用
    Runnable接口和Callable接口的区别
    Java中的常见数学运算
    mkdir()和mkdirs()区别
    面试小问题——Object中有哪些常用方法?
    面试小问题——什么是多态?
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/13508166.html
Copyright © 2011-2022 走看看