Python类、对象与继承

类只是创建对象所需的定义或蓝图。如果为一家公司搭建管理系统,则员工信息是这个系统中最重要的部分。因此,如果以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 2

table 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 2

table 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.0

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
打完折后的价格是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

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值