13_Python的面向对象编程-类class,对象object,实例instance

1.面向对象概述

    1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组
    2.对象是由类实例化出来的一个具体的对象
        属性: 对象拥有的名词,用变量表示
        行为: 对象拥有的动作,用方法表示
    3.面向对象是把一切看成对象,对象和对象之间用方法建立关联关系
    4.面向过程是一件事怎么一步一步实现,面向对象是一件事情谁去实现
    5.可以用类创建一个或多个此类的对象,类中的变量和方法能被此类所创建的所有对象所共同拥有
    6.面向对象编程语言的特征封装,继承,多态
    7.类和对象流程图: https://www.processon.com/view/link/5ee0e5b5f346fb1ae558f314

类            对象      属性             方法
车            BYD       E6(京A.88888)    行驶
狗            小京巴     户籍号:00001     喝水
示例:

2.类的概述

    1.类的创建语法
        class 类名(继承列表):
            """类文档字符串"""
            实例方法(methd) 的定义
            类变量(classVariable) 的定义
            类方法(@classmethod) 的定义
            静态方法(@staticmethod) 的定义
    1.类名必须是标识符,即由数字字母下划线组成且不能以数字开头和不能是关键字,建议用大驼峰命名法,如: WebServer
    2.类名实质上就是变量,它绑定一个类实例,属性是这类事务具有什么样的特征,方法是这类事务具有什么样的行为
    3.在Python2中不指定继承object会定义经典类,Python3中无论是否制定继承object,都会创建新式类

# Python2中不指定继承object会创建经典类
class A:
    pass


# Python2中定义新式类
class B(object):
    pass


# Python3中无论是否制定继承object,都会创建新式类
class C:
    pass
示例:

    4.使用help(__builtins__)可以查看Python中所有的类的继承派生关系

# 查看类的继承派生关系
help(__builtins__)
示例:

3.实例与实例化概述

    实例概述:
        1.实例就是有类诞生出的一个对象,实例有自己的作用域或名字空间,可以为该实例添加实例变量
        2.同一个类实例化出的对象是不同的个体,实例可以调用类的方法和访问类中的类变量
    实例化概述:
        1.实例化就是类创建一个对象,并返回此实例对象的引用关系的过程
        2.语法: obj = 类名([创建传参列表])  # 创建这个类的实例化对象,并返回此实例对象的引用关系 []里的形参可省略

class Dog:  # 定义一个狗类
    pass
    
    
dog1 = Dog()  # 用类来创建一个对象用dog1绑定
print(id(dog1))  # 打印dog1所在的内存地址
dog2 = Dog()  # 创建第二个对象 用dog2绑定
print(id(dog2))
# 判断两只示例化出来的狗对象是不是同一条狗
print(dog1 is dog2)  # False
示例:

4.类的组成成员: 字段,方法,静态属性

    1.公有静态字段: 属于类在内存中只保存一份,类和实例都可以访问,类内部和派生类中也可以访问
    2.私有静态字段: 属于类在内存中只保存一份,仅类内部可以访问
    3.公有普通字段: 属于对象在每个对象中都要保存一份,实例可以访问,类内部和派生类中也可以访问
    4.私有普通字段: 属于对象在每个对象中都要保存一份,仅类内部可以访问
    5.实例方法: 属于类在内存中只保存一份,由对象调用,至少一个self参数,实例可以访问,类内部和派生类中也可以访问
    6.私有方法: 属于类在内存中只保存一份,仅类内部可以访问,命名以双下划线开头,没有参数
    7.类方法: 属于类在内存中只保存一份,由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类赋值给cls
    8.静态方法: 属于类在内存中只保存一份,由类调用,无默认参数
    9.静态属性: 属于类在内存中只保存一份,实例可以访问,类内部和派生类中也可以访问

class ClassMember:
    """此示例阐述类的组成成员"""


    company_name = "x公司"  # 公有静态字段(公有静态变量,类变量),类和实例都可以访问,类内部和派生类中也可以访问
    __iphone = "135xxxxxxxx"  # 私有静态字段(私有静态变量,私有类变量),仅类内部可以访问

    def __init__(self, name, age):  # 初始化方法
        self.name = name  # 公有普通字段(实例属性),实例可以访问,类内部可以访问,派生类中可以访问
        self.__age = age  # 私有普通字段(私有实例属性),仅类内部可以访问

    def func1(self):  # 实例方法,至少有一个self参数,实例可以访问,类内部可以访问,派生类中可以访问
        pass

    def __func(self):  # 私有方法,仅类内部可以访问
        print(666)

    @classmethod  # 类方法
    def class_func(cls):
        """定义类方法,至少有一个cls参数"""
        print("类方法")

    @staticmethod  # 静态方法
    def static_func():
        """定义静态方法,无默认参数"""
        print("静态方法")

    @property  # 静态属性,将方法伪装成属性来使用
    def prop(self):
        pass
示例:

5.公有静态字段与私有静态字段

1.公有静态字段概述(公有静态变量,公有类变量) 1.类变量类可以通过类名.来访问,类内部和派生类中也可以访问 2.类变量是类的属性,此属性属于类,不属于此类创建的实例 3.类变量可以通过此类实例化对象访问,可以通过实例的 '__class__'属性间接修改 示例1: class Human: total_count = 0 # 类变量, 用于记录对象的个数 print(Human.total_count) h1 = Human() print(h1.total_count) # 0 # 不会出错 Human.total_count = 1 # 修改类变量 h1.total_count = 2 # 添加了自己的实例属性total_count h1.__class__.total_count = 3 # 间接修改类变量 示例2: class Human: total_count = 0 # 类变量,用于记录对象的个数 def __init__(self, name): self.name = name self.__class__.total_count += 1 # 人数加1 print(name, "对象创建") def __del__(self): self.__class__.total_count -= 1 # 总人数减1 print("当前对象的个数是:", Human.total_count) # 0 h1 = Human("张飞") h2 = Human("赵云") print("当前对象的个数是:", Human.total_count) # 2 del h2 # 或 h2 = None print("当前对象的个数是:", Human.total_count) # 1 示例3: class C: name = "公有静态字段" def func(self): print(C.name) class D(C): def show(self): print(C.name) C.name # 类访问 obj = C() obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 派生类中可以访问 2.私有静态字段(私有静态变量,私有类变量) 1.用户在创建类是可以在属性名前加双下划线来声明该属性只属于类所有,仅类内部可以访问 2.私有类变量不能被外界的实例对象直接访问,也不可以通过该类直接访问,不可在派生类中访问 3.私有类变量可以通过_类名__变量名来间接访问 示例: class C: __name = "私有静态字段" def func(self): print(C.__name) class D(C): def show(self): print(C.__name) # C.__name # 不可在外部访问 obj = C() # obj.__name # 不可在外部访问 obj._C__name # 可以通过_类名__属性名来间接访问 obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 不可在派生类中访问 3.变量的赋值规则: 首次为变量赋值则创建此变量,再次为变量赋值则改变变量的绑定关系 4.在定义变量时如果不确定设置什么初始值,可以设置为None 5.删除变量del语句,语法: del 类名.变量名 6.类名.变量查找顺序: 先从本类空间找,如果找不到,再从父类找... 7.可以通过类的__dict__方法查看类的所有属性所在的字典 8.可以通过dir函数查看类的所有属性和方法

6.公有普通字段与私有普通字段

1.公有普通字段概述(公有实例属性,公有实例变量) 1.每个实例可以有自己的属性,实例属性的使用语法: 实例.属性名 2.实例属性: 对象可以访问,类内部和派生类中也可以访问 示例1: class C: def __init__(self): self.foo = "公有普通字段" def func(self): print(self.foo) # 类内部访问 class D(C): def show(self): print(self.foo) # 派生类中访问 obj = C() obj.foo # 通过对象访问 obj.func() # 类内部访问 obj_son = D() obj_son.show() # 派生类中访问 示例2: class Dog: def __init__(self): self.name = None self.color = None dog1 = Dog() dog1.kinds = "京巴" # 为dog1绑定的实例添加kinds属性 dog1.color = "白色" # 添加属性 print(dog1.kinds, dog1.color) # 访问属性 dog1.color = '黄色' # 修改dog1.color 的绑定关系 print(dog1.color) 2.私有普通字段概述(私有实例属性,私有实例变量) 1.每个实例可以有自己的私有属性,称为私有实例属性或私有实例变量,使用语法: 实例.类中的引用方法名 2.私有实例属性: 仅类内部可以访问,但可以通过_类名__属性名来间接访问 示例1: class C: def __init__(self): self.__foo = "私有字段" def func(self): print(self.foo) # 类内部访问 class D(C): def show(self): print(self.foo) # 派生类中访问 obj = C() obj.__foo # 通过对象访问会报错 obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 派生类中访问会报错 示例2: class Women: def __init__(self, name): self.name = name self.__age = 18 def secret(self): print("%s的年龄是%d" % (self.name, self.__age)) xiaomei = Women("小美") # print(xiaomei.__age) # 私有属性不能被外界的实例对象直接访问 xiaomei.secret() # 在对象内部的方法可以直接访问对象的私有属性 print(xiaomei._Women__age) # 私有属性可以通过_类名__属性名来间接访问 xiaomei.__dict__ # {'name': '小美', '_Women__age': 18} dir(xiaomei)[0:3] # ['_Women__age', '__class__', '__delattr__'] 3.属性的赋值规则: 首次为属性赋值则创建此属性,再次为属性赋值则改变属性的绑定关系 4.在定义属性时如果不确定设置什么初始值,可以设置为None 5.删除属性del语句,语法: del 对象.属性名 示例: class Student: pass stu = Student() stu.name = 'xiaozhang' # 创建属性 print(stu.name) del stu.name # 删除此属性 print(stu.name) # 属性错误,因为属性已经不存在了 6.对象.属性查找顺序: 先从对象空间找,如果找不到,再从类空间找,再找不到,再从父类找... 7.可以通过对象的__dict__方法查看对象所有属性所在的字典 8.可以通过dir函数查看对象的所有属性和方法

7.实例方法与私有方法

1.实例方法概述 1.实例方法的实质是函数,是定义在类内的函数,用于描述一个对象的行为,让此类型的全部对象都拥有相同的行为 2.实例方法至少有一个self参数代表调用这个方法的实例,声明该方法是实例方法 3.实例方法对象可以访问,类内部和派生类中也可以访问 4.实例方法的调用语法: 实例.实例方法名(调用参数) 类名.实例方法名(实例, 调用参数) 示例: class C: def __init__(self): pass def add(self): print("this is add") class D(C): def show(self): print("this is show") def func(self): self.show() obj = D() obj.show() # 通过对象访问 obj.func() # 类内部访问 obj.add() # 派生类中访问 D.func(obj) # 类名调用 2.私有方法概述 1.用户在创建类是可以在方法名前加双下划线(__方法名)来声明该属性只属于类所有 2.私有方法不能被外界的实例对象直接访问 3.用户自定义的私有方法可以通过_类名__方法名来间接访问 示例: class Women: def __init__(self, name): self.name = name self.__age = 18 def __secret(self): print("%s的年龄是%d" % (self.name, self.__age)) xiaomei = Women("小美") # xiaomei.__secret() # 私有方法不能被外界的实例对象直接访问 xiaomei._Women__secret() # 私有方法可以通过_类名__方法名来间接访问 xiaomei.__dict__ # {'name': '小美', '_Women__age': 18} dir(xiaomei)[0:3] # ['_Women__age', '_Women__secret', '__class__'] 3.删除方法del语句,语法: del 类名.方法名 4.类名.方法查找顺序: 先从本类空间找,如果找不到,再从父类找... 5.可以通过对象的__dict__方法查看对象所有属性所在的字典 6.可以通过dir函数查看对象的所有属性和方法

8.类方法与静态方法和静态属性(@classmethod, @staticmethod, @property)

1.类方法 classmethod 类方法概述: 1.类方法是操作类的方法,类方法属于类,不属于该类创建的对象 2.类方法需要使用 @classmethod 装饰器定义,第一个参数用来绑定类,约定写为cls 3.类和对象实例都可以调用类方法,类方法不能访问此类创建的对象的属性 4.类方法不用对象命名空间中的内容,而是用到了类命名空间中的变量(静态属性),或者类方法,静态方法 示例1: class A: v = 0 # 类变量 @classmethod def get_v(cls): # 此方法是类方法 return cls.v a = A() a.get_v() # 0 A.get_v() # 0 a.__dict__ # {} 示例2: class Goods: __discount = 0.8 def __init__(self, price): self.__price = price @property def price(self): return self.__price * Goods.__discount @classmethod def change_discount(cls, num): cls.__discount = num # 商场的程序 apple = Goods(10) banana = Goods(15) print(apple.price,banana.price) Goods.change_discount(1) print(apple.price,banana.price) 2.静态方法 staticmethod 静态方法概述: 1.静态方法是定义在类的内部的函数,此函数作用域是类的内部 2.静态方法需要使用@staticmethod 装饰器定义,定义上与普通函数的定义相同,不需要传入self和cls 3.静态方法只能凭借该类和实例来调用,不能访问类变量和实例变量 4.如果一个类里面的方法既不需要用到self中的资源,也不用cls中的资源,就将这个方法定义成一个静态方法 示例1: class A: @staticmethod def myadd(a, b): # 此方法是静态方法 return a + b print(A.myadd(100, 200)) # 300 a = A() print(a.myadd(300, 400)) # 300 示例2: # 装饰登录功能 class Person: @staticmethod def login(): # 动词 动作 属于某一个对象 pass class Student(Person): pass class Manager(Person): pass class Course: pass class Classes: pass 3.静态属性 property 静态属性概述: 1.将方法伪装成一个静态属性,代码上没有什么提升只是更合理,静态属性本质就是实现了 get,set,delete 三种方法 2.静态属性需要使用 @property 装饰器定义,只和实例对象绑定既可以访问实例属性也可以访问类的属性 3.property的构造方法中有个四个参数 1.第一个参数是方法名,调用 对象.属性 时自动触发执行方法 2.第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法 3.第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法 4.第四个参数是字符串,调用 对象.属性.__doc__ 时此参数是该属性的描述信息 4.@方法名.setter装饰器: 修改property装饰的属性时会被调用这个装饰器装饰的方法 除了self外还有一个参数是被修改的值 5.@方法名.deleter装饰器: 当要删除被property装饰的属性时会被调用这个装饰器的方法 实际不会删除被property装饰的方法,而是在执行'del 类名.属性'删除操作时执行这个装饰器的方法 6.定义property属性有两种方式: 在方法上应用装饰器和在类中定义值为property对象的类属性 示例1: # property属性定义方式: 类中定义值为property对象的类属性 class Foo: def get_bar(self): return 'Tom' # 必须两个参数 def set_bar(self, value): return return 'set value' + value def del_bar(self): return 'Tom' BAR = property(get_bar, set_bar, del_bar, 'description') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法: get_bar obj.BAR = "Cat" # 自动调用第二个参数中定义的方法: set_bar方法,并将"Cat"当作参数传入 del Foo.BAR # 自动调用第三个参数中定义的方法: del_bar方法 obj.BAE.__doc__ # 自动获取第四个参数中设置的值: description 示例2: # property属性定义方式: 在方法上应用装饰器 class Person: def __init__(self, name, age): self.name = name if type(age) is int: self.__age = age else: print('你输入的年龄的类型有误,请输入数字') @property def age(self): return self.__age @age.setter def age(self, a1): '''判断,你修改的年龄必须是数字''' if type(a1) is int: self.__age = a1 else: print('你输入的年龄的类型有误,请输入数字') @age.deleter def age(self): del self.__age p1 = Person('帅哥', 20) print(p1.age) # 20 print(p1.__dict__) # {'name': '帅哥', '_Person__age': 20} p1.age = 23 print(p1.age) # 23 del p1.age 示例3: # property属性定义方式: 在方法上应用装饰器 class Money(object): def __init__(self): self.__money = 0 # 使用装饰器对money进行装饰,那么会自动添加一个叫money的属性,当调用获取money的值时调用装饰的方法 @property def money(self): return self.__money # 使用装饰器对money进行装饰,当对money设置值时,调用装饰的方法 @money.setter def money(self, value): if isinstance(value, int): self.__money = value else: print("error:不是整型数字") a = Money() a.money = 100 print(a.money) # property属性定义方式: 在方法上应用装饰器 class Money(object): def __init__(self): self.__money = 0 def getMoney(self): return self.__money def setMoney(self, value): if isinstance(value, int): self.__money = value else: print("error:不是整型数字") # 定义一个属性,当对这个money设置值时调用setMoney,当获取值时调用getMoney money = property(getMoney, setMoney) a = Money() a.money = 100 # 调用setMoney方法 print(a.money) # 调用getMoney方法 示例4: # property属性定义方式: 在方法上应用装饰器,实现类型检测功能 class People: def __init__(self, name): self.name = name # 实例化就触发property @property def name(self): # return self.name # 无限递归 print('get------>') return self.DouNiWan @name.setter def name(self, value): print('set------>') if not isinstance(value, str): raise TypeError('必须是字符串类型') self.DouNiWan = value @name.deleter def name(self): print('delete------>') del self.DouNiWan p1 = People('echo') # self.name实际是存放到self.DouNiWan里 p1.name = 1 示例5: # property属性定义方式: 在方法上应用装饰器,验证@deleter不会删除被property装饰的方法 class A: def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, new_name): if type(new_name) is str: self.__name = new_name @name.deleter def name(self): def self.__name a = A("Ccoc") print(a.name) a.name = "echo" del a.name # 看似是删除了name属性,实际是删除了__name私有属性 # print(a) 示例6: # property属性定义方式: 在方法上应用装饰器,让调用看起来更加合理 class Pager: def __init__(self, current_page): # 用户当前请求的页码(第一页,第二页...) self.current_page = current_page # 每页默认显示10条数据 self.per_items = 10 @property def start(self): val = (self.current_page - 1) * self.per_items return val @property def end(self): val = self.current_page * self.per_items return val p = Pager(1) p.start # 就是起始值,即: m p.end # 就是结束值,即: n 示例7: # property属性定义方式: 在方法上应用装饰器,取代getater和seatter以及delattr方法 class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 @property def price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price @price.setter def price(self, value): self.original_price = value @price.deleter def price(self): del self.original_price obj = Goods() obj.price # 获取商品价格 obj.price = 200 # 修改商品原价 del obj.price # 删除商品原价 示例8: # property属性定义方式: 使用类属性的方式创建property属性改写示例7 class Goods(object): def __init__(self): # 原价 self.original_price = 100 # 折扣 self.discount = 0.8 def get_price(self): # 实际价格 = 原价 * 折扣 new_price = self.original_price * self.discount return new_price def set_price(self, value): self.original_price = value def del_price(self): del self.original_price PRICE = property(get_price, set_price, del_price, '价格属性描述...') obj = Goods() obj.PRICE # 获取商品价格 obj.PRICE = 200 # 修改商品原价 del obj.PRICE # 删除商品原价 4.静态方法,类方法,静态属性综合示例 class Room(object): tag = 1 def __init__(self, wight, length): self.wight = wight self.length = length @property def car_area(self): return self.length * self.wight + self.tag @classmethod def tell_info(cls): print(cls) print("-->", cls.tag) @staticmethod def run(a, b): print("%s %s 正在跑步" % (a, b)) # 静态属性: 将类的函数属性@property装饰后,是对象以数据属性的方式调用 # 只和实例对象绑定-->即可以访问实例属性也可以访问类的属性 p1 = Room(10, 20) print("类属性", p1.tag) print("实例对象调用静态属性", p1.car_area) # 类方法: 将类的函数属性@classmethod装饰后,不用创建实例对象,调用类的函数属性 # 只和类绑定-->可以访问类属性,不能访问实例属性 Room.tell_info() # 静态方法: 将类的函数属性@staticmethod装饰后,不创建和创建实例对象,都可以调用类的函数属性 # 即不和类绑定也不和实例对象绑定-->不能访问类属性,也不能访问实例属性,是类的工具包 Room.run("co1", "co2") p2 = Room(20, 20) p2.run("co3", "co4") 5.Django框架中应用了property属性 class WSGIRequest(http.HttpRequest): def __init__(self, environ): script_name = get_script_name(environ) path_info = get_path_info(environ) if not path_info: # Sometimes PATH_INFO exists, but is empty (e.g. accessing # the SCRIPT_NAME URL without a trailing slash). We really need to # operate as if they'd requested '/'. Not amazingly nice to force # the path like this, but should be harmless. path_info = '/' self.environ = environ self.path_info = path_info self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/')) self.META = environ self.META['PATH_INFO'] = path_info self.META['SCRIPT_NAME'] = script_name self.method = environ['REQUEST_METHOD'].upper() _, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', '')) if 'charset' in content_params: try: codecs.lookup(content_params['charset']) except LookupError: pass else: self.encoding = content_params['charset'] self._post_parse_error = False try: content_length = int(environ.get('CONTENT_LENGTH')) except (ValueError, TypeError): content_length = 0 self._stream = LimitedStream(self.environ['wsgi.input'], content_length) self._read_started = False self.resolver_match = None def _get_scheme(self): return self.environ.get('wsgi.url_scheme') def _get_request(self): warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or ' '`request.POST` instead.', RemovedInDjango19Warning, 2) if not hasattr(self, '_request'): self._request = datastructures.MergeDict(self.POST, self.GET) return self._request @cached_property def GET(self): # The WSGI spec says 'QUERY_STRING' may be absent. raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '') return http.QueryDict(raw_query_string, encoding=self._encoding) # ############### 看这里看这里 ############### def _get_post(self): if not hasattr(self, '_post'): self._load_post_and_files() return self._post # ############### 看这里看这里 ############### def _set_post(self, post): self._post = post @cached_property def COOKIES(self): raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '') return http.parse_cookie(raw_cookie) def _get_files(self): if not hasattr(self, '_files'): self._load_post_and_files() return self._files # ############### 看这里看这里 ############### POST = property(_get_post, _set_post) FILES = property(_get_files) REQUEST = property(_get_request)

9.作用于类的内置函数(isinstance issubclass object super vars type)

1.isinstance函数 isinstance(obj, class_or_tuple): 返回这个对象是否是某个类的对象,或者某些类中的一个类的对象,如果是则返回True,否则返回False 示例: class Foo(object): pass obj = Foo() isinstance(obj, Foo) # True isinstance(1, int) # True isinstance("", (int, str, list)) # # True 2.issubclass函数 issubclass(cls, class_or_tuple): 判断一个类是否是继承自其它的类,如果此类cls是class或tuple中的一个派生子类则返回True,否则返回False 示例: class A: pass class B(A): pass class C(B): pass class D(B): pass issubclass(B, A) # True issubclass(C, B) # True issubclass(D, C) # False issubclass(C, (int, str)) # False 3.object函数 object函数概述: 1.object类是Python中所有类的基类,如果定义一个类时没有指定继承哪个类,则默认继承object类 2.object没有定义__dict__所以不能对object类实例对象尝试设置属性 3.object函数返回一个新的无特征对象,obj = object() 示例1: class A: pass # 默认继承object类 print(issubclass(A,object)) # True # object类定义了所有类的一些公共方法 print(dir(object)[0:5]) # ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__'] # object函数返回一个新的无特征对象 obj = object() type(obj) # object print(obj) #