python 基础(十)

面向对象

一、概念

  1. 类(class): 用来描述具有相同属性和方法的对象的集合 对象是类的实例化

  2. 类变量:类变量在整个实例化的对象中是共用的。定义在类中 并且是函数体外的

  3. 实例变量:只能作用于 当前类的实例化后的某一个对象上

  4. 实例: 创建一个类的具体实例 类的具体化对象

  5. 方法: 就是类中的函数

  6. 属性:就是类中的函数外的变量

二、命名方式

  1. 大驼峰 首字母大写

  2. 见名知意

  3. 严格区分大小写

三、类的定义

class 类名:

​ 属性

​ 方法

其中的属性 和方法 都是可有可无(语法上没有问题的)

四、类中的属性和方法的调用

对象 = 类名([参数])

对象.属性名

对象.方法名([参数])

五、self

self代表当前类的实例 而非类

在你实例化类的时候 会自动传入 方法需要有一个参数来去接收当前实例化后的的对象 这个self对象 就是外部实例化的那个对象

self的作用:

  1. 可以去创建对象属性

  2. 在类的内部调用属性和方法 和外部一样 对象.属性/方法名 只是里面的对象 统一叫self(别的名称也可以 不规范)

证明

 
class Person:
    sex = '男'
    def mouth(self,*args,**kwargs):
        print(args,kwargs)
    def test(abc):
        print(abc)
p1 = Person()
p2 = Person()
print(p1)
p1.test()
print(p2)
p2.test()
print(p1.sex)
class Person:
    sex = '男'
    def createVar(selfvar):
        self.var = var
        print(self.__dict__)
p = Person()
p.__dict__
p.createVar('我是实例化后的p')
__dict__ 以字典的形式 返回对象或者类中的属性和方法
 

六、属性和方法注意事项

属性:

当给类里面的属性 使用对象.属性名 = 值得时候 并不是将类里面得属性值进行修改 而且在当前对象里面创建了一个同名得属性 在查找得时候 会优先取当前对象查找 如果查找不到 则去类中查找 对象和类是一个引用关系 当类里面得属性发生修改 则全部对象全部对应发生改变

方法:

方法就是函数,参数和return返回值使用都一样

七、例子

class ATM:
    money = 0
    user = ''
    def setMoney(self,money):
        money = int(money)
        if money>=100:
            self.money += money
            print('你好{} 您得余额为 {}'.format(self.user,self.money))
        else:
            print('请输入正确金额')
    def getMoney(self,money):
        money = int(money)
        if money<=self.money and self.money>=100 and money>=100:
            self.money -= money
            print('余额为{}'.format(self.money))
        else:
            print('请输入正确金额')
    def lookMoney(self):
        print('您好{} 您得余额为{}'.format(self.user,self.money))
zhangsan = ATM()
zhangsan.user = 'zhangsan'
zhangsan.setMoney(100)
zhangsan.getMoney(100)
zhangsan.lookMoney()
lisi = ATM()
lisi.user = '李四'
lisi.setMoney(1000)
lisi.getMoney(100)
lisi.lookMoney()
 

八、对象属性和类属性

  1. 在对象中 创建了和 类中相同得属性名得时候 在调用会优先调用对象得属性

  2. 对象属性可以被删除 删除以后会去类中查找

  3. 对象属性优先级高于类属性

  4. 对象不可以删除或修改类里面得属性和方法你只有使用权力

  5. 在类中定义得属性 称之为类属性 在对象或者类中方法创建得属性 称之为对象属性

(1) 绑定对象属性的方法

实例:

class A:
    x = 'x' #此刻为类属性
    def createVar(self,var):
        self.var = var  #此属性为对象属性
a = A()
a.x = 'x'  #对象属性
del a.x  #此刻删除得为 对象a里面得x属性
del a.x   #此刻在删除 为删除类里面得x  不允许修改
print(a.x)
 

(2) 绑定类属性

类名.新得属性名 = 属性值

实例

class A:
    pass
a = A()
A.newAttr = '给类绑定新属性'
print(a.newAttr) #给类绑定新属性
 

注意:

注意绑定类属性得顺序 需要在对象实例化或者对象调用属性得上方进行绑定类属性 说白了就是 先绑定 后调用(因为加载顺序)

(3) 系统函数 对类/对象属性得操作(返回bool值)

hasattr() 判断当前对象/类是否存在某属性

setattr() 设置对象/类属性

getattr() 获取对象/类属性

实例

class A:
    message = '他年方25 英年早泄'
    def demo(self):
        print('你是怎样调用得呢?',self)
a = A()
b = A()
#判断当前类/对象 是否存在某属性 返回布尔值
print(hasattr(a,'message')) #True
print(hasattr(A,'message')) #True
print(hasattr(a,'name')) #False
#通过函数获取属性值
print(getattr(a,'message')) #他年方25 英年早泄
print(getattr(a,'aaaa','404')) #NOT Found http状态码
setattr(a,'x','x') #给对象 a绑定对象属性x 只有当前对象a能够获取到
setattr(A,'x','x') #给类A绑定类属性以后 所有对象都能够获取到
print(a.x)
print(b.x)
 

九、给对象和类绑定方法

(1) 给对象绑定方法

from types import MethodType

实例

class A:
    pass
from types import MethodType
def func(self):
    print(self)
a = A()
b = A()
a.func = MethodType(func,a)
# print(a.__dict__) #{'func': <bound method func of <__main__.A object at 0x000001EC1DCDF1D0>>}
a.func() #只有当前对象有此方法
b.func() 
 

只有当前对象有此方法

(2) 给类绑定方法

class A:
    def demo(self):
        pass
def func(self):
    print('你调用我了')
A.func = func #这个操作和下面得代码是一样得
"""
a = func
print(a)
a(1)
"""
# print(A.__dict__)
a = A()
# print(a.func) #打印函数体
# print(a.demo) #打印函数体
A.func('传参')
b = A()
b.func()
 

所有得对象都会有类绑定得方法 (等学完继承以后 不要这么干 因为一旦改动 所有得对象 都会拥有)

十、__slots__ 限制对象属性得添加

作用: 能够对对象属性添加起到限制作用 如果添加了slots以外得属性 则抛出attributeError得异常

实例:

class A:
    __slots__ = ('name','sex','age') #注意事项 只能使用括号里面得属性 系统属性也不能够使用了
 

十一、私有属性、私有方法

(1) 私有属性

__private_attr:俩个下划线作为开头 ,声明当前属性为私有 只有在类得内部可以使用 不能在类得外部被使用或者 直接访问 在类得内部调用为 self.__private_attr

私有属性得访问

对象/类._类名__私有属性名

其实你的私有属性在存储得时候 自动转换成了 _类名__私有属性名 所以你在调用 __私有属性名得时候 抛出属性错误得异常

注意:

虽然这样也可以访问到 但是强烈建议不要这么做 不同得版本解释器可能会将 _类名 改成不同得名字称

实例

class B:
    __girlFriend = '小凤'
    def YongMyself(self):
        print('自己内部可以用',self.__girlFriend)
    def update(self):
        # self.__age = 20 #此刻在类得内部创建了一个对象私有属性 __age
        self.__dict__['__age'] = 20  #获取对象中得公有属性 __age 并修改其值
zhangsan = B()
print(zhangsan.girlFriend) #AttributeError: 'A' object has no attribute 'girlFriend'
zhangsan.YongMyself() #可以通过共有得方法 获取私有属性得值  也就是私有在类得内部十可以调用得
print(B.__dict__)  #查看B类中得所以属性和方法 
print(zhangsan._B__girlFriend) #通过对象调用私有属性 
print(B._B__girlFriend)  #通过类来调用私有属性
zhangsan.__age = 18 #创建了一个名字为__age 得公有对象属性
zhangsan.update() 
print(zhangsan.__age)
print(zhangsan.__dict__)
print(zhangsan._B__age)
 

(2) 私有方法

__private_method: 方法名以俩个下划线作为开头 声明当前方法为 私有方法 只能在类得内部调用 不能够在外部访问 在类得内部调用为 self._private__method

私有方法得访问

对象/类._类名__私有方法

其实你的私有方法在存储得时候 自动转换成了 _类名__私有方法名 所以你在调用 __私有方法名得时候 抛出属性错误得异常

实例

class A:
    def __demo(self):
        print('你能不能调用到我呢?')
    def public_method(self): #在公有方法中 调用私有方法
        self.__demo()
a = A()
a._A__demo() #私有方法得调用
A._A__demo(a)
 

注意:

私有属性和方法 不会被继承

十二、装饰器

可以将方法 像属性一样去调用 起到对值得过滤

  1. @property 对于属性进行获取

  2. @方法名.setter 对属性进行赋值/修改值

实例

 
class A:
    sex = 'women'
    __age = 20
    @property
    # def age(self):
    def age(self):
        return self.__age
    @age.setter
    def age(self,age):
        if 1<=age<=100:
            self.__age = age
        else:
            raise ValueError
 a = A()
a.age = 101
print(a.age)
 

十三、继承

概念: 面向对象编程 最主要得作用就是 代码得重用 实现重用得方法就是 继承机制

被继承得类 称之为 父类、基类和超类(Base class Super class)

继承得类称之为 子类

(1) 单一继承

通常一个类 如果没有继承得父类得时候 可以继承object类(它是所有类得父类)

格式

class Son(BaseClass):
    pass
 

实例

class Demo(object):
    pass
#此刻为继承所有类得超类object   不论你是否继承object  都会默认继承
class People(object):
    name = ''
    age = 0
    __weight = 0
    money = 100000
    __smallThree = '小凤'
    #定义一个构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("{}说 我今年{}岁了".format(self.name,self.age))
    def __privateSon(self):
        print('私生子 不会被继承')
class Son(People):
    def smallMother(self):
        # print(self.__smallThree)
        # print(self._People__smallThree) #私有属性和方法 不会被继承
        print(self.name)
        print(self.money)
    def demo(self):
        # self.speak()
        # self.__privateSon() #会在类中查找 但是查找得为 _Son__privateSon()
        self._People__privateSon()
son = Son('张三',18,70)
print(son.name,son.money) #拥有了父类得所有公用得东西
son.smallMother()
son.demo()
 

注意:

  1. 父类得私有属性和方法 是不会被继承 但是可以通过 self.__属性名self._类名__方法名 去调用父类得私有属性和方法

  2. 当子类中存在和父类同名得方法时 会将父类得方法覆盖掉(父类方法得重写)

十四、父类方法得调用

方法1

​ super().方法名()

方法2

​ super(类名,self).方法名

方法3

​ 类名.方法名(self)

实例

class Animal(object):
    def __init__(self,name):
        self.name = name
    def saySomething(self):
        print('我是{}'.format(self.name))
dog = Animal('dog')
class Dog(Animal):
    def __init__(self,name):
        super().__init__(name)
        # Animal.__init__(self,name) #传入当前对象 self
        # super(Dog,self).__init__(name) #单一继承得时候 不建议加参数  默认会传递   当有多继承得时候 需要使用 传递参数 因为这时候需要指定你想调用得是 哪一个父类得里面得方法
dog = Dog('dog')
dog.saySomething()
 

十五、多继承

主体结构
 
class SonClass(base1,base2...):
    pass
 

将要多继承得类名 写入括号中,以逗号隔开 如果有重复得方法得存在 注意类得摆放顺序

实例:

#动物类
class Animal:
    def animal(self):
        print('属于动物类')
#跑得类
class Run(Animal):
    def run(self):
        print('跑的类')
#能飞得类
class Fly(Animal):
    def fly(self):
        print('飞的类')
#哺乳类
class Lactation(object):
    def lactation(self):
        print('哺乳类')
#鸟类
class Bird(object):
    def bird(self):
        print('鸟类')
#蝙蝠继承了哺乳类
class BianFu(Fly,Lactation):
    pass
bianfu = BianFu()
bianfu.animal()
bianfu.lactation()
class Dog(Run,Lactation):
    pass
dog = Dog()
dog.animal()
dog.run()
 

注意:

当进行多继承的时候 会将父类中所有的方法和属性 进行继承 如果存在重复的方法 且没有指定的时候 会按照进程父类的摆放顺序 从左至右依次搜索 直到搜索到指定的方法为止

多继承的父类方法的调用

 
class A:
    def func(self):
        print('我是A类的func方法')
    def a(self):
        print('我是A类的a方法')
class B:
    def func(self):
        print('我是B类的func方法')
    def b(self):
        print('我是B类的a方法')
class D:
    def func(self):
        print('我是d类的func方法')
    def d(self):
        print('我是d类的d方法')
class C(A,B,D):
    def func(self):
        # B.func(self)
        #当使用super时候 没有传递参数 则按照从左至右的顺序查找
        # super().func()
        # super(C,self).func() #从C类开始向右查找
        # super(A,self).func() #从A类开始 向右查找
        super(B,self).func() #从B类开始 向右查找
c = C()
c.func()
c.d()
 

十六、类常用的属性

  1. 类名.__doc__ 类的说明

  2. 类名.__name__ 返回当前的类名

  3. 类名.__base__ 返回当前的一个父类

  4. 类名.__bases__ 返回当前的多个父类

  5. 类名.__dict__ 以字典的形式 返回当前类或者对象中的所有的信息

 
class A:
    """
    这是当前类的说明
    """
    def __init__(self):
        pass
class C:
    pass
class B(A,C):
    pass
print(A.__doc__) #当前类的说明
print(A.__name__) #返回当前的类名
print(B.__base__) #返回当前的父类
print(B.__bases__) #返回当前的多个父类
print(B.__dict__) #返回当前B类里面的所有信息
 

十七、静态方法和类方法

在python的类中 存在3种方法

  1. 静态方法

  2. 类方法

  3. 实例方法

(1) 静态方法

被@staticmethod 装饰器修饰的称之为静态方法

可以在当前类实例化 或者没有实例化的情况下去调用

实例

class A:
    def func(self):
        print('func方法')
    #此刻static其实就是一个普通的函数  并且不能够调用类中的属性和方法
    @staticmethod  #只是将 类名.方法名 进行了合理化的处理
    def static(self):
        # return '静态方法'
        self.func()
a = A()
# a.static(a)
A.func()
 

(2) 类方法

被@classmethod 装饰器修饰的称之为类方法

实例

class A:
    name = '张三'
    def func(self):
        print(self.name,self.sex,'func方法')
    #可以在不进行当前类的实例化 就进行调用 (在方法的内部去实例化)
    #既可以使用类去调用 也可以使用对象调用
    @classmethod
    def classMethod(cls,name,sex):
        # print(cls.name)
        obj = cls()
        obj.name = name
        obj.sex= sex
        return obj
a = A()
# a.classMethod()
# print(A.name)
# print(A.classMethod('张三','男'))
A.classMethod('张三','男').func() #将类的实例化 在方法种 节省了实例 并进行对象的连贯操作
 

十八、类的专有方法

  • __init__:构造方法 在生成对象时 自动调用 作为类的初始化

  • __del__ :析构方法 释放对象的时候时候 可以被del 进行触发

  • __str__ 将值转换成易于人阅读的形式

  • __repr__ 转换为程序员的阅读方式

  • __getattr__ 当获取不存在的属性的时候被触发

  • __add__ 元算符重载 在俩个对象进行相加 的时候触发 (注意 只能是俩个对象相加)

  • __setitem__ 按照索引赋值

  • __getitem__ 按照索引取值

  • __delitem__ 按照索引删除值

  • __len__ 计算当前的长度

(1)__init____del__的使用

 
class A:
    f = ''
    def __init__(self,path,method="w"):
        self.f = open(path,method)
    def Read(self,size=1024):
        return self.f.read(size)
    def Write(self,con):
        try:
            return self.f.write(con)
        except:
            return False
    def __del__(self):
        self.f.close()
a = A('./a.txt')
a.Write('xx\n')
a.Write('yy\n')
del a #手动触发
r = A('./a.txt','r')
print(r.Read())
# while True:
#     pass
 

(2) __str____repr__ 的使用

str和repr 都是用来显示内容的 str面向用户 repr是面向程序员的
触发的时机是不同的
class A:
    f = ''
    def __init__(self):
        pass
    def Read(self,size=1024):
        pass
    def Write(self,con):
        pass
    def __str__(self):
        return '这是一个空的类'
    def __repr__(self):
        return 'repr'
    def __del__(self):
        pass
a = A()
 

注意

  1. str和repr如果单独出现的时候 触发机制都可以

  2. 如果共同存在一个类中的化

    • str

      print(对象)/str(对象)

    • repr

      repr(对象)/在终端下 直接输出对象

(3)__getattr__ 当调用不存在的属性的时候被触发

class A:
    f = ''
    def __getattr__(self, item):
        # return '{}属性不存在'.format(item)
        raise AttributeError("{}属性不存在".format(item))
a = A()
a.x #会触发 getattr方法
 

(4) __add__运算符重载

class A:
    def __init__(self,num):
        self.num = num
    def __add__(self, other):
        return A(self.num+other.num)
    def __str__(self):
        return "num = "+str(self.num)
a = A(1)
b = A(2)
print(a+b)
 

(5) len,setitem,getitem,delitem的操作

将类模拟成字典的操作
class MyDict:
    def __init__(self,key,value):
        self.Dict = {}
        self.Dict[key] = value
    def __setitem__(self, key, value):
        self.Dict[key] = value
    def __getitem__(self, item):
        return self.Dict[item]
    def __len__(self):
        return len(self.Dict)
    def __delitem__(self, key):
        del self.Dict[key]
    def __str__(self):
        return str(self.Dict)
Dict = MyDict('a','a')
Dict['b'] = 'b'
del Dict['a']
print(Dict)
print(len(Dict))
print(Dict['b'])
print(Dict['x'])
#将值转换成平方在返回
class Indexer:
    def __getitem__(self, item):
        return item**2
obj = Indexer()
# print(obj[2])
for i in range(5):
    print(obj[i])
 

猜你喜欢

转载自www.cnblogs.com/gugubeng/p/9715561.html