类只是创建对象所需的定义或蓝图。如果为一家公司搭建管理系统,则员工信息是这个系统中最重要的部分。因此,如果以Employee为名称创建一个类,则这个类将作为创建Employee对象的蓝图。此外,虽然实例和对象在现实世界中常互换使用,但理解两者之间的区别同样重要。对象表示类的内存地址,而实例只是类在特定情况下的虚拟副本。假设存在一个类Employee,并有6条员工信息。每位员工均为不同对象,并且都有不同的个人信息,如姓名、电子邮件id、年龄等。每个实例都是单一对象的唯一实际表现。对象使用实例执行操作。对象是通用的,但实例是特定的。每个实例都被赋值,同时使实例之间得以区分。因此,对象是通用的,但实例是类的实际表现。实例表示特定的对象,也表示在内存中创建的单个对象。这将在下一节中详细解释。
Python 中的一切均为对象,都是类的实例。类是一种用户定义的数据类型。具有该
数据类型的对象,称为该类的实例。所有的Python类都是object类的子类 可以直接调用object类中的方法 这些方法称为特殊方法
1.创建类和实例化对象
x = 1 print(type(x)) y = 'string' print(type(y))<class 'int'>
<class 'str'>
在定义类之后,可定义类的属性和方法。方法为类中定义的函数,它与给定的对象一起执行。方法需要访问使其执行的对象,因此,类中每个方法的第一个参数是当前实例,按照惯例,该实例被称为self。在方法内部使用self来访问存储在对象中的数据。self是调用该方法的实例化对象
Python 定义了一些名称以双下划线开始和结束的特殊方法(也称为函数)。最常用的是_init_()函数。此方法用于初始化类实例,也可称为类构造函数。因为每当Py·thon 创建该类实例时,会自动调用__init()_函数,所以只需将其定义,而不必显式调用。除此之外,_init_()函数并非类的强制性设置,而是可选的。下面定义_init_()函数。
class Employee: def __init__(self, name, email,department,age,salary): self.name = name self.email = email self.department = department self.age = age self.salary = salary def print_employee(self): print(self.name, self.email, self.department, self.age, self.salary) e1 = Employee("Alex","<EMAIL>qq.com",'Python',18,'12000') e1.print_employee()输出:Alex <EMAIL>qq.com Python 18 12000
1.1析构函数__del__
析构函数是在对象结束其生命周期时,系统自动执行的特殊函数。此方法的目的是释放对象占用的内存。在Python中,因为遵循用于内存管理的垃圾回收机制,所以析构函数需求较少,但它在Python中的确存在,并且实际中无须显式定义。析构函数是_del_()方法。未显式定义时会自动调用来销毁对象并清理对象占用的
当程序不再需要一个Python对象时,系统必须把该对象所占用的内存空间释放出来,这个过程称垃圾回收(GC),Python会自动回收所有对象所占用的内存空间,因此开发者无须关心对象垃圾回收的过程。
del e1 print(e1.Total_no_of_employees)Traceback (most recent call last):
NameError: name 'e1' is not defined
1.2检查属性 dict
print(e1.__dict__){'name': 'Alex', 'email': '<EMAIL>qq.com', 'department': 'Python', 'age': 18, 'salary': '12000'}
self.attributeName 是所有类共享的 className. attributeName是可以被覆盖的 如每次创建一个新对象 total_tables的值加1
class Table: total_tables = 0 def __init__(self, name): self.name = name self.total_tables = self.total_tables + 1 print("table {},name:{}".format(self.total_tables,self.name)) table1 = Table("Table 1") table2 = Table("Table 2")输出:
table 1,name:Table 1
table 1,name:Table 2table 1,name:Table 3
class Table: total_tables = 0 def __init__(self, name): self.name = name Table.total_tables = Table.total_tables + 1 print("table {},name:{}".format(self.total_tables,self.name)) table1 = Table("Table 1") table2 = Table("Table 2") table3 = Table("Table 3")输出:
table 1,name:Table 1
table 2,name:Table 2table 3,name:Table 3
1.3__call__
判断对象中的特性到底是属性还是方法,需要进一步判断它是否可调用。程序可通过判断该属性(或方法)是否包含__call__属性来确定它是否可调用
class User:
def __init__(self,name,passwd):
self.name = name
self.passwd =passwd
def vaildLogin(self):
print("验证%s的登录"%self.name)
u=User('crazyit','leegang')
#判断u.name是否包含__call__方法,即判断它是否可调用
print(hasattr(u.name,'__call__'))#False
#判断u.passwd是否含__call__方法,即判断它是否可调用
print(hasattr(u.passwd,'__call__'))#False
#判断u.validLogin是否包含__call__方法,即判断它是否可调用
print(hasattr(u.vaildLogin,'__call__'))#True
2.继承
面向对象语言允许重用代码。继承就是将代码的可重用性提升到另一个层次的方式。继承中存在超类和子类。子类拥有超类中不存在的属性。假设为狗舍开发软件程序,因此应有dog类,其具有所有狗的共同特征。然而,谈到具体品种时,因为每个品种间均存在差异,所以可为每个品种创建类。这些类将继承 dog类的共同特征,并在其基础上增添自身属性,使每个品种不同于其他品种。现在,逐步尝试创建一个类,然后创建其子类。
通过继承,可在不修改现有类的情况下创建新类,现有的类称为基类,继承的新类称为派生类,基类的特性(方法和属性)可以被派生类访问。
class Dog(): def print_info(self): print("我有属于狗类,有四条腿,两只耳朵") class Dog1(Dog): def __init__(self,name): self.name = name print("我是{}".format(name)) def print_color(self): print("{}我是白色的".format(self.name)) dog1 = Dog1("金毛") dog1.print_info() dog1.print_color()输出:
我是金毛
我有属于狗类,有四条腿,两只耳朵
金毛我是白色的
子类可以重写基类的方法,但对其他子类不影响 子类(派生类)可以覆盖基类的任意方法
# 定义基类 class Dog: def print_info(self): print("我属于狗类,有四条腿,两只耳朵") class Dog1(Dog): def __init__(self,name): self.name = name print("我是{}".format(name)) def print_color(self): print("{}我是白色的".format(self.name)) # Dog1重写基类的print_info 方法 def print_info(self): print("我属于狗类中的金毛狮王类,有四条腿,两只耳朵") class Dog2(Dog): def __init__(self): print("我是Dog2") dog1 = Dog1("dog1") dog1.print_info() dog1.print_color() dog2 = Dog2() dog2.print_info() #对Dog2没有如何影响输出:
我是dog1
我属于狗类中的金毛狮王类,有四条腿,两只耳朵
dog1我是白色的
我是Dog2
我属于狗类,有四条腿,两只耳朵
2.1super方法
super方法可以让子类在继承基类的基础上,添加其他代码
# 定义基类 class Dog: def print_info(self): print("我属于狗类,有四条腿,两只耳朵") class Dog1(Dog): def __init__(self,name): self.name = name print("我是{}".format(name)) def print_color(self): print("{}我是白色的".format(self.name)) # Dog1重写基类的print_info 方法 def print_info(self): print("我属于狗类中的金毛狮王类,有四条腿,两只耳朵") class Dog2(Dog): def __init__(self): print("我是Dog2") def print_info(self): super().print_info() print("我更属于狗类中的阿拉斯加类")输出:
我是dog1
我属于狗类中的金毛狮王类,有四条腿,两只耳朵
dog1我是白色的
我是Dog2
我属于狗类,有四条腿,两只耳朵
我更属于狗类中的阿拉斯加类
3.有界方法 无界方法和静态方法 (实例方法、类方法和静态方法)
3.1实例方法
实例方法或者叫对象方法,指的是我们在类中定义的普通方法 def 自定义方法名。
只有实例化对象之后才可以使用的方法,该方法的第一个形参接收的一定是对象本身(self)!
class Dog2(Dog): def __init__(self): print("我是Dog2") def print_info(self): super().print_info() print("我更属于狗类中的阿拉斯加类")加粗的就是实例化方法 使用实例化对象调用
dog2 = Dog2() dog2.print_info()
3.2静态方法
在实例化方法上面添加 @staticmethod (@property 是不能修饰带参数的方法的)可以有参数也可以无参数。
一般用于和类对象以及实例对象无关的代码。
调用: 类名.类方法名(或者对象名.类方法名)。
class Game: @staticmethod def play(): print("倒计时") print(1) print(2) print(3) Game.play() game = Game() game.play()倒计时
1
2
3
倒计时
1
2
3
3.3类方法
无需实例化,可以通过类直接调用,方法的第一个参数接收的一定是类本身
在方法上面添加@classmethod即类方法 方法的参数为默认为cls cls指向类对象本身
当一个方法中只涉及到静态属性(类变量)的时候可以使用类方法(类方法用来修改类属性)。
把所有实例化对象的静态属性(类变量)一同更改
调用: 对象名.类方法名或 类名.类方法名
class Food: discount = 1 def __init__(self, name, price): self.name = name self.price = price print(f"{name}的初始价格是:", self.price) @classmethod def food_discount(cls, dis_count): cls.discount = dis_count * cls.discount def food_price(self,dis_count): self.price = dis_count * self.price def food_Discountsprice(self): print(f"打完折后的价格是{self.price * self.discount}") # Food.food_discount(0.3) bread = Food("Bread", 20) milk = Food("Milk", 10) bread.food_price(0.7) milk.food_price(0.4) bread.food_Discountsprice() milk.food_Discountsprice()输出:
Bread的初始价格是: 20
Milk的初始价格是: 10
打完折后的价格是14.0
打完折后的价格是4.0class Food: discount = 1 def __init__(self, name, price): self.name = name self.price = price print(f"{name}的初始价格是:", self.price) @classmethod def food_discount(cls, dis_count): cls.discount = dis_count * cls.discount def food_price(self,dis_count): self.price = dis_count * self.price def food_Discountsprice(self): print(f"打完折后的价格是{self.price * self.discount}") Food.food_discount(0.3) bread = Food("Bread", 20) milk = Food("Milk", 10) # bread.food_price(0.7) # milk.food_price(0.4) bread.food_Discountsprice() milk.food_Discountsprice()Bread的初始价格是: 20
Milk的初始价格是: 10
打完折后的价格是6.0
打完折后的价格是3.0
3.4@property
被 @property
装饰的方法是获取属性值的方法,被装饰方法的名字会被用做 属性名
class Food: discount = 1 def __init__(self, name, price): self.name = name self.price = price print(f"{name}的初始价格是:", self.price) @classmethod def food_discount(cls, dis_count): cls.discount = dis_count * cls.discount def food_price(self,dis_count): self.price = dis_count * self.price @property def food_Discountsprice(self): # print(f"打完折后的价格是{self.price * self.discount}") return self.price * self.discount Food.food_discount(0.3) bread = Food("Bread", 20) milk = Food("Milk", 10) print(bread.food_Discountsprice) print(milk.food_Discountsprice)输出:Bread的初始价格是: 20
Milk的初始价格是: 10
6.0
3.0
拓展:
1 调用时名称以下划线开头、结尾的方法称为特殊方法或者魔术方法,如__init__ __dict__ __del__ __add__ __str__特殊方法不可以显示调用,在创建类的对象时被自动调用(幕后自动调用)。
假设有两个银行账户,输出两个对象的值,得到对象的内存地址而非数据,如果将两个对象相加求余额 会报错
class Bank: def __init__(self,account,balance): self.balance = balance self.account = account b1 = Bank("Bank1",100) b2 = Bank("Bank2",100) print(b1) print(b2) print(b1+b2)输出
unsupported operand type(s) for +: 'Bank' and 'Bank'
通过魔术方法__str__ 和 __add__方法定义操作符功能
class Bank: def __init__(self, account, balance): self.balance = balance self.account = account def __str__(self): str1 = "account:" + self.account + "balance:" + self.balance return str1 def __add__(self, other): balance = int(self.balance) + int(other.balance) return balance b1 = Bank("Bank1", '100') b2 = Bank("Bank2", '120') b3 = Bank("Bank3", '130') print(b1) print(b2) print(b3) print(b1 + b2 )输出:account:Bank1balance:100
account:Bank2balance:120
account:Bank3balance:130
220
2 定义在类中但在方法外的变量称为类变量
3 类属性对类中所有的对象均相同 self.attribute