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
继承 支持多继承
- 如果一个类没有继承任何类,则默认继承object
- 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类
- 是所有类的父类
- dir 可以查看里面所有类
- 有一个--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__方法
多态
略
特殊属性
例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
完,其实还不全,还得多看书,谨记学习..
本文来自博客园,作者:咸瑜,转载请注明原文链接:https://www.cnblogs.com/bi-hu/p/16977181.html