python12 类

类的创建

语法:

class Student: # 规范的话 肯定是首字母大写的,Java也是
	pass

组成:

  • 类属性
  • 实例方法
  • 静态方法
  • 类方法

创建对象

下面例子是创建类,和创建对象的例子:

# 作者:咸瑜
# 代码时间:2022/12/2


class People:
    name = ''  # 类属性
    age = 0

    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 实例方法 self 相当于本身类[类似Java 的 this]
    def word(self):  # self是存在的,如果不写也存在,可以换一个名字
        print(self.name, "正在工作")

    # 静态方法
    @staticmethod
    def staticMethod():
        print("人的静态方法")

    # 类方法
    @classmethod
    def classMethod(cls):  # cls是存在的,如果不写也存在,可以换一个名字
        print("人的类方法")


people = People("咸瑜", 19)

print(people)
print(id(people))
print(type(people))

# ---------------------
print(people.name)
print(people.age)
people.word()
people.staticMethod()
people.classMethod()

# <__main__.People object at 0x0000021BB010CF70>
# 2317941264240
# <class '__main__.People'>
# 咸瑜
# 19
# 咸瑜 正在工作
# 人的静态方法
# 人的类方法

调用类属性 类方法 静态方法

# 作者:咸瑜
# 代码时间:2022/12/2


class People:
    name = ''  # 类属性
    age = 0
    address = '北京市'

    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 实例方法 self 相当于本身类[类似Java 的 this]
    def word(self):  # self是存在的,如果不写也存在,可以换一个名字
        print(self.name, "正在工作")

    # 静态方法
    @staticmethod
    def staticMethod():
        print("人的静态方法")

    # 类方法
    @classmethod
    def classMethod(cls):  # cls是存在的,如果不写也存在,可以换一个名字
        print("人的类方法")

# ------------------------类属性使用------------------------------
# 作者:咸瑜
# 代码时间:2022/12/2


class People:
    name = ''  # 类属性
    age = 0
    address = '默认市'

    # 初始化方法
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 实例方法 self 相当于本身类[类似Java 的 this]
    def word(self):  # self是存在的,如果不写也存在,可以换一个名字
        print(self.name, "正在工作")

    # 静态方法
    @staticmethod
    def staticMethod():
        print("人的静态方法")

    # 类方法
    @classmethod
    def classMethod(cls):  # cls是存在的,如果不写也存在,可以换一个名字
        print("人的类方法")


# ------------------------类属性使用------------------------------
p1 = People("咸瑜", 19)
p1.address = "咸瑜的家"
p2 = People("大佬", 20)


print(p1.address)  # 北京市
print(p2.address)  # 北京市
print(People.address)  # 北京市

People.address = "广东省中山市"

print(p1.address)  # 咸瑜的家
print(p2.address)  # 广东省中山市
print(People.address)  # 广东省中山市

p1.address = "广东省惠州市"
p2.address = "广东省广州市"
People.address = "广东省深圳市"

print(p1.address)  # 广东省惠州市
print(p2.address)  # 广东省广州市
print(People.address)  # 广东省深圳市

# ------------------------类方法使用------------------------------
p1.classMethod()  # 人的类方法
# ------------------------静态方法使用------------------------------
p1.staticMethod()  # 人的静态方法


对象动态绑定属性和方法

其实可以在对象中添加某些属性和方法:

# 作者:咸瑜
# 代码时间:2022/12/2

def show():
    print("Show函数")


class People:
    name = ''  # 类属性
    age = 0


p1 = People()
p1.address = "广东省中山市"
print(p1.address)  # 动态绑定了 一个 address的属性

p1.show = show  # 动态的绑定了一个 show 函数为自己的方法
p1.show()

# 广东省中山市
# Show函数


People.NewParam = "xx"
print(p1.NewParam)  # 不仅对象可以,类也可以,当类添加了绑定了新属性,那么凡是他的对象也相应的添加了绑定的新属性

封装、继承、多态

封装:没有特别的修饰关键字,直接在私有属性或方法面前添加连个 __ 即可:

class People:
    name = ''  # 类属性
    __age = 0  # 私有属性 age  只能在People 类中使用


p1 = People()
print(p1.age)  # 报错 AttributeError: 'People' object has no attribute 'age'
print(People.age)  # 报错 AttributeError: 'People' object has no attribute 'age'

当然如果你是牛鬼蛇神,那也可以强制访问:

class People:
    name = ''  # 类属性
    __age = 0  # 私有属性 age  只能在People 类中使用


p1 = People()
# print(dir(p1)) # 可以查看类或对象里面的一些属性和方法
# ['_People__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
# 可以看到有一个name ,还有一个 _People__age
# 我们尝试去访问 _People__age
print(p1._People__age)  # 0

继承 支持多继承

image-20221203151618559

  1. 如果一个类没有继承任何类,则默认继承object
  2. Python支持多继承 | 定义子类时,必须在其构造函数中调用父类的构造函数
# 作者:咸瑜
# 代码时间:2022/12/5

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def info(self):
        print('姓名:{0},年龄:{1}'.format(self.name, self.age))


class Student(Person):
    def __init__(self, name, age, score):
        super().__init__(name, age)
        self.score = score


s1 = Student('咸瑜', 20, '10086')
s1.info()

# 运行: 姓名:咸瑜,年龄:20

多继承

# 作者:咸瑜
# 代码时间:2022/12/5

class A(object):
    def a(self):
        print('a')


class B(object):
    def b(self):
        print('b')


class C(A, B):
    def __init__(self):
        super().a()
        super().b()


c = C()
# 运行:
# a
# b

重写

可以对某个属性或方法进行重写

可以重写方法的时候用 super().xxx()进行调用父类的方法[原方法]

class A(object):
    def a(self):
        print('a')


class B(object):
    def b(self):
        print('b')


class C(A, B):
    # 重写a
    def a(self):
        super().a()  # 调用父类a的a方法
        print("c-a")

    # 重写b
    def b(self):
        super().b()  # 调用父类b的b方法
        print("c-b")


c = C()
c.a()
c.b()
# 运行
# a
# c-a
# b
# c-b
# 作者:咸瑜
# 代码时间:2022/12/5

class A(object):
    age = 97

    def a(self):
        print('a-a')


class B(object):
    age = 98

    def a(self):
        print('b-a')


class C(A, B):
    # age = 99

    # 重写a
    def a(self):
        super().a()  # 父类如果存在一样的方法,那么进行重写,重写的是 第一个父类的方法[权重第一个最大]
        print("c-a")
        print(self.age)  # 97 所以权重是第一个大,A 和 B 都有age 但是调用了 a的age[97]


c = C()
c.a()

# 运行
# a-a
# c-a
# 97

Object类

  1. 是所有类的父类
  2. dir 可以查看里面所有类
  3. 有一个--str--方法可以返回对象的描述,其实底层就是print,所以我们可以进行重写

例:

# 作者:咸瑜
# 代码时间:2022/12/10

class Test():
    name = "XianYu"

    def __str__(self):
        return "我是Test类,我的name属性是 {0}".format(self.name)


t = Test()
print(dir(t)) # 查看所有方法
print(t) #相当于执行了 __str__方法

多态

特殊属性

image-20221211133452263

例1 特殊属性

# 作者:咸瑜
# 代码时间:2022/12/10

class A:
    pass

class B:
    pass

class C(A, B):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def test(self):
        print("test方法")

s1 = C("咸瑜", 18)
print(s1.__dict__)  # 查看该对象的所有的属性[字典] {'name': '咸瑜', 'age': 18}
print(s1.__class__)  # 查看对象的所属的类 <class '__main__.C'>
# ------------------------------------------------------------------------------------------------------------------
print(C.__dict__)  # 查看类的所有的方法[字典] {'__module__': '__main__', '__init__': <function C.__init__ at 0x0000027EE0C0BF70>, 'test': <function C.test at 0x0000027EE0C0B8B0>, '__doc__': None}
print(C.__bases__)  # 查看类的继承(父类) (<class '__main__.A'>, <class '__main__.B'>)
print(C.__base__)  # 查看类的继承(父类) 按照权重的 =  “取第一继承(基类)” <class '__main__.A'>
print(C.__mro__)  # 查看类的继承结构 (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
print(C.__subclasses__())  # 查看类的子类列表 []
print(A.__subclasses__())  # 查看类的子类列表 [<class '__main__.C'>]

例2 特殊方法

__ add __ 例:

# 作者:咸瑜
# 代码时间:2022/12/10

num1 = 10
num2 = 20
print(num1 + num2)  # 30
# -----------------------------------------------------
print(num1.__add__(num2))  # 30
# 作者:咸瑜
# 代码时间:2022/12/10

class A:
    def __init__(self, name):
        self.name = name;

    def __add__(self, other):
        return self.name + other.name


a = A("咸瑜")
a1 = A("真帅")
print(a + a1) # 咸瑜真帅 ,如果没重写__add__那么会报错!

__ len __ 例:

lst = [11,22,33,44,55]
print(lst.__len__()) # 5 输出lst的对象长度

__ new __ 和 __ init __ # 慢慢看下面的代码和运行结果

# 作者:咸瑜
# 代码时间:2022/12/10

class Person(object):
    def __new__(cls, *args, **kwargs):
        print("__new__被调用执行了,cls的id值为{0}".format(id(cls)))
        obj = super().__new__(cls)
        print("创建的对象的id为:{0}".format(id(obj)))
        return obj

    def __init__(self, name, age):
        print("__init__被调用了,self的id值为: {0}".format(id(self)))
        self.name = name
        self.age = age


print("object这个类对象的id为:{0}".format(id(object)))
print("Person这个类对象的id为:{0}".format(id(Person)))

xianyu = Person("咸瑜", 18)
print("xianyu这个Person类的实例对象的id:{0}".format(id(xianyu)))

cs2 = Person("测试2", 18)
print("cs2这个Person类的实例对象的id:{0}".format(id(cs2)))

# object这个类对象的id为:140713303293440
# Person这个类对象的id为:1378169221296

# __new__被调用执行了,cls的id值为1378169221296
# 创建的对象的id为:1378170620656

# __init__被调用了,self的id值为: 1378170620656
# xianyu这个Person类的实例对象的id:1378170620656

## 解析:  先调用了 __new__ 在调用了 __init_。
## __new__方法的cls,其实就是Person类的地址[这个是固定死的,不同机器、编译器不同]
## __new__ 方法中返回的地址,那么也就是__init__中self的地址,__init__中self的地址其实也就是实例xianyu的地址了!

类的浅拷贝和深拷贝

浅拷贝

Python一般都是浅拷贝,拷贝时,对象的子对象(属性等)内容不进行拷贝(还是原来的指向),所以浅拷贝拷贝出来的新对象会指向原对象

# 作者:咸瑜
# 代码时间:2022/12/12 21:07

class A:
    pass


class B:
    pass


class C:
    def __init__(self, a, b):
        self.a = a
        self.b = b


a1 = A()
b1 = B()
c1 = C(a1, b1)
c2 = c1

# 这就是浅拷贝【直接指向不是Copy,但可以看出是 “浅拷贝”】
print(id(c1))  # 2791427358672
print(id(c2))  # 2791427358672

print("a1", id(a1))
print("b1", id(b1))
print("c1.a:", id(c1.a))
print("c1.b:", id(c1.b))

# 下面运行结果证明拷贝的是 “浅拷贝”
# a1 1458764107728
# b1 1458764107680
# c1.a: 1458764107728
# c1.b: 1458764107680


import copy

# 利用Copy可以 进行对象的复制,但是这个也是属于浅拷贝[子对象不会进行拷贝]
test = copy.copy(c1)
print(id(c1))  # 1760579866480
print(id(test))  # 1760579864656
print(id(c1.a))  # 1760579866576
print(id(test.a))  # 1760579866576
print(id(c1.b))  # 1760579866528
print(id(test.b))  # 1760579866528

深拷贝

用copy 模块模块的 deepcopy 函数,可以递归拷贝对象中包含的子对象[属性等..],源对象和拷贝出来的对象,完全是两个独立互不相同的。

# 作者:咸瑜
# 代码时间:2022/12/12 21:07

class A:
    pass


class B:
    pass


class C:
    def __init__(self, a, b):
        self.a = a
        self.b = b


a1 = A()
b1 = B()
c1 = C(a1, b1)

print("a1", id(a1))
print("b1", id(b1))
print("----------------------------------------")
print("c1", id(c1))
print("c1.a", id(c1.a))
print("c1.b", id(c1.b))
print("----------------------------------------")

import copy
test = copy.deepcopy(c1)
print("test", id(test))
print("test.a", id(test.a))
print("test.b", id(test.b))

# 可以看出,下面运行结果中,深拷贝的test和源对象完全是不一样的,而且对象里面的子对象也完全不一样
# a1 2367899553744
# b1 2367899553696
# -------------------------------
# c1 2367899553648
# c1.a 2367899553744
# c1.b 2367899553696
# -------------------------------
# test 2367899551920
# test.a 2367899551152
# test.b 2367899551008

完,其实还不全,还得多看书,谨记学习..

posted @ 2022-12-12 21:35  咸瑜  阅读(15)  评论(0编辑  收藏  举报