# 1.实例化一个类:
- 基本格式:变量 = 类名() # 实列化一个对象
* 案例1
# 定义了一个Person类 class Person: count = 1 age = 18 # 实例化对象 # 执行class时就会得到类对象,并将其赋值给变量名(Person) p = Person() # p是一个变量,指向了Person类产生的对象 print(Person) # Person是一个类 print(p) # p就成了Person类产生的对象 """ # 结果 <class '__main__.Person'> <__main__.Person object at 0x0000022294ED7F98> """
# 2.查看类的信息
- 2.1.可以通过默认内置变量来检查类和对象的所有成员
- 对象所有成员检查:obj.__dict__
- 类所有成员检查:class_name.__dict__
- 2.2.使用help()函数
- 2.3.使用dir()函数
- 2.4.使用type()查看实例的类型归属
- 2.5.使用内置方法isinstance(实例, ClassName)来测试一个对象是否为某各类的实例
* 案例2
# 定义了一个Person类 class Person: name = "China" age = 18 # 实例化对象 p = Person() # 1.查看成员 # 1.1查看对象的成员 print(p.__dict__) # 空字典 # 1.2查看类的成员 print(Person.__dict__) # 2.使用help()函数查看 print(help(p)) # print(help(Person)) # 两个会是一样的结果,指向关系 # 3.使用dir()可以查看对象的属性和方法 print(dir(Person)) # print(dir(p))效果一样 # 4.查看归属 print(type(p), type(Person)) # <class '__main__.Person'> <class 'type'> # 5.判断关系 print(isinstance(p,Person)) # 如果是该类的实例返回True,否则返回False # 注意要判断的p和类Person一定要存在,不然会报错。
# 3.对类的属性进行操作
- 3.0.属性和变量区别:
- 变量:根据不同的位置,有不同的访问权限
- 属性:只能通过变量名来引用。
- 3.1.访问对象成员
- 使用点操作符
- obj.成员属性名称
- obj.成员方法
- 3.2.增加属性
- 动态增加增加
变量.属性名 = 值
- 实例对象可以通过字典__dict__进行增加和修改
- 通过类的初始化方法(构造方法)
__init__ 方法
- 3.3.删除属性
- 一般情况下,属性存储在__dict__的字典当中
- 有些内置对象没有这个__dict__ 属性
- 一般对象可以直接修改__dict__属性
- 但类对象的__dict__为只读模式
- 默认无法修改
- 可以通过setarr方法修改
* 案例3
class Person: age = 18 p = Person() # 实例化对象 # 1.进行访问 # 1.1通过类名进行访问 print(Person.age) # 18 # 1.2通过实例化对象进行访问 print(p.age) # 18 """-----------------------------------------------------------""" # 2.增加操作 # 注意:如果要增加的变量已存在,则修改 # 2.1动态增加 # 2.1.1直接通过类名进行属性增加 Person.name = 'abc' print("Person:", Person.__dict__) print("p:", p.__dict__) # 空字典 # 2.1.2通过实例进行增加 p.zeng = 100 # 只在p里面增加,不影响Person print("Person:", Person.__dict__) print("p:", p.__dict__) # {'zeng': 100} # 2.2使用构造方法(属于方法的操作) """-----------------------------------------------------------""" # 3.删除操作 # 注意: # del p.age #会报错,p内不存在age # 可以进行del p.zeng,因为前面增加了zeng属性 # 3.1实例删除 del p.zeng # 3.2直接通过类 del Person.age print("Person:", Person.__dict__) # 缺少了age属性 print("p:", p.__dict__) # 空字典
# 4.类的属性的存储问题
- 4.1一般情况下,属性存储在__dict__的字典当中。
- 实例对象一般可以直接修改__dict__属性
- 类对象的__dict__为只读
- 4.2实例对象和类对象是存储在不同一块空间。
- 4.3访问时:
- 通过类对象:直接在类对象中查找
- 通过实例对象:优先在实例对象内部查找,没有找到需要的,就到指向的类对象中查找。
- 4.4修改时的区别:
- 通过实例对象进行增加、删除或者修改属性的值,都是在实例对象内部进行,对类对象没有影响
- 通过类对象进行增加、删除属性时:
- 对实例化对象内部没有的属性产生影响。
- 对实例化对象内部已拥有相同的属性不产生影响。
* 案例4.1
# 1.一般情况下,属性存储在__dict__的字典当中 class Person(): age = 18 p = Person() print(p.__dict__) # 空字典{} print(p.age)# 18 # 虽然是空字典但是能访问Person的属性,指向的关系 """-----------------------------------------------------------""" # 1.1可以通过字典__dict__修改实例对象的属性 p.__dict__ = {"count":2,"sex":"男"} """-----------------------------------------------------------""" # 1.2类对象的__dict__为只读 #Person.__dict__ = {"count":3,"age":15} #Person.__dict__ = {"sex":"男"} #会报错, """-----------------------------------------------------------""" print(Person.__dict__) print(p.__dict__) # {'count': 2, 'sex': '男'}
* 案例4.2
# 2.实例对象和类对象是存储在不同一块空间。 class Person(): age = 19 pass """-----------------------------------------------------------""" # 2.1内存上开辟了新空间,两者的地址不一样 p = Person() print(id(p), id(Person)) """-----------------------------------------------------------""" # 2.2修改和新增类的地址都不变 p.age = 18 Person.name = "aaaa" print(id(p), id(Person)) """-----------------------------------------------------------""" # 2.3属性修改后的地址变化和列表的修改变化一样 p.pets = ["car","dog"] print(p.pets,id(p.pets)) p.pets = ["car", "dog", "fish"] # 直接修改 print(p.pets,id(p.pets)) p.pets.append("iiiii") # 进行追加操作 print(p.pets,id(p.pets)) """-----------------------------------------------------------""" print(p.__dict__) #{'age': 18, 'pets': ['car', 'dog', 'fish', 'iiiii']} print(Person.__dict__) # Person 中z属性没发生改变
* 案例4.3
# 3.访问时: class Person(): age = 19 pass p = Person() p.age = 18 print(p.age) # 18 # 优先访问自己的内部属性 print(Person.age) # 19 # Person.age没有被修改, # 通过类访问,直接指向类对象的age
* 案例4.4
# 4.修改时: class Person(): age = 18 pass p = Person() # 4.1未修改前类对象和实例对象指向同一个属性。 print("Person:",Person.age, id(Person.age)) print("p :", p.age, id(p.age)) print("---"*10) # 4.2通过实例对象进行修改,没有对类对象产生影响 p.age = 28 print("Person:",Person.age, id(Person.age)) print("p :", p.age, id(p.age)) print("---"*10) # 4.3通过类对象进行修改 Person.age = 38 # 4.3.1实例对象p内部有age属性,无法造成影响 print("Person:",Person.age, id(Person.age)) print("p :", p.age, id(p.age)) print("---"*10) # 4.3.2实例对象p内部没有age属性,无法造成影响 del p.age # 删除p中的age print("p :", p.age, id(p.age)) # 此时访问p.age则指向Person.age Person.age = 48 # 通过类对象修改age print("Person:",Person.age, id(Person.age)) print("p :", p.age, id(p.age))
# 5.对类的方法进行操作
- 5.1方法的存储:方法存储在类里面,不管是哪一种类型的方法,都是存储在类当中,没有在实例当中
* 案例5.1
class Person(): # 1.实例方法:默认第一个参数需要接受到一个实例 def eat(self): # 必须要有参数,默认是self print("这是一个实例方法",self) # 2.类方法:默认第一个参数需要接受到一个实例 @classmethod def leifangfa(cls): print("这是一个类方法",cls) # 33.静态方法:第一个参数啥也不默认接受 @staticmethod def jingtaifangfa(): print("这是一个静态方法") p = Person() # 查看参数 print(p) p.eat() # self和p的地址一样 Person.leifangfa() # <__main__.Person object at 0x0000022294ECFE48> Person.jingtaifangfa() # <class '__main__.Person'> # 查看方法存储 print(p.__dict__) # 空字典{} print(Person.__dict__)
- 5.2实例方法调用方式:本质就是找到函数本身调用
- 标准调用(推荐使用):使用实例调用
- 类调用: 使用类名进行调用,没有意义
- 间接调用
* 案例5.2
class Person: def eat(self,food): print("我在吃饭",self, food) # 1.标准调用 p = Person() print(p) # p就时self,系统自动传入 print(p.eat("rich")) # 这是实例化 可以只写一个参数,self是默认参数,可以不用写 # 标准调用,实例化调用 不用写第一个参数self # 2.类调用 print(Person.eat) # Person.eat 是一个函数 print(Person.eat(555,"FISH"))# 必须要有两个参数,不然会报错 # self = 555, food = FISH # 3.间接调用 func = Person.eat # Person.eat 是一个函数,func指向Person.eat print(func(123,"DDD")) # self = 123, food = DDD
- 5.3类方法
* 案例5.3
class Person(): @classmethod # 通过这个装饰器 def leifangfa(cls, a): print("这是一个类方法",cls, a) # 1.类调用 print(Person.leifangfa(123)) # 2.间接调用 func = Person.leifangfa print(func(456)) # 3.实例化,标准调用 p = Person() print(p.leifangfa(789))
- 5.4静态方法
* 案例5.4
class Person(): @staticmethod def leifangfa(self): # 参数没有默认接受 print("这是一个静态方法",self) # 1.类调用 print(Person.leifangfa(1)) # 2.间接调用 func = Person.leifangfa print(func(2)) # 3.实例化,标准调用 p = Person() print(p.leifangfa(3))
- 5.4不同方法的调用
* 案例5.5
class Person(): age = 18 # 能通过实例和类访问 def shilifangfa(self): print(self) print(self.age) print(self.num) @classmethod def leifangfa(cls): print(cls) print(cls.age) # print(Person.num) 无法访问 @staticmethod def jingtaifangfa(): print("jingtai") p = Person() p.num = 10 # 只能通过实例访问,无法通过类访问: Person.num # 调用类属性 print(Person.age) # 18 print(p.age) # 18 # 调用实例属性 print(p.num) # 19 print('--'*20) print(p.shilifangfa()) print('--'*20) print(p.leifangfa()) print('--'*20) print(p.jingtaifangfa()) """ # 结果 18 18 10 ---------------------------------------- <__main__.Person object at 0x000001AA7705B668> 18 10 None ---------------------------------------- <class '__main__.Person'> 18 None ---------------------------------------- jingtai None """
# 6.相关的操作
- 6.1构造器:由__new__()和__init__()组成
- 对象实例化的时候首先调用方法__new__()创建对象
- 第一个参数不是self而是这个类(cls),其他参数直接传递个__init__()。
- 需要返回一个实例对象,通常是cls这个类实例化的对象。
- 如果用户不提供自己的__new__(),Python自动调用object.__new__()方法。
- 之后调用__init__()对其进行初始化
- __init__()一般用来为数据成员设置初值或进行其他初始化工作
- 在创建对象时被自动调用和执行。
- 如果用户没有设计构造函数,Python会自动提供一个默认的构造函数
- 返回值一定时None
* 案例 6.1.1
# 构造器的实践 class Person(str): def __new__(cls, string): string = string.upper() print("__new__") print(cls) # 第一个参数是这个类 return str.__new__(cls, string) def __init__(self, v): print("__init__") # print(v) # i love chian a = Person("i love chian") # 1.实例化后先执行__new__(),打印__new__ # 2.接着执行__init__(),打印__init__ print(a) # 打印返回的类实例化的对象
* 案例6.1.2
# 构造函数式 class Person(): def __init__(self, n, a): self.name = n self.age = a p1 = Person("sx",19) print(p1.__dict__) # {'name': 'sx', 'age': 19} # print(Person.age) # 不能访问__init__的内容 print(p1.name,p1.age) # sx 19
- 6.2析构器:由__del__()函数构成
- 一般用来释放对象占用资源或收回对象空间时被自动调用和自行。
- 如果用户没有设计析构函数,Python会自动提供一个默认的析构函数进行必要的清理工作。
* 案例6.2
# 构造函数式 class Person(): def __init__(self, n, a): self.name = n self.age = a print("构造函数执行完毕") def __del__(self): print(self) print("对象被清除了") p1 = Person("sx",19) del p1 """ # 结果 构造函数执行完毕 <__main__.Person object at 0x000001333CEF0EB8> 对象被清除了 """