零基础小白 Python这样学就对啦!——07篇

类 和 对象

目前我们所学的python中的内置类型都是对象------内置对象,内置对象有时候不能满足我们的需求,需要自定义一些对象。

10, 20, 30, -40, a=10, b=20等等等,都是整数,对其进行抽象------int类。

python 中一切都是对象。

类也是一个对象。

1 类的定义 与 实例化对象

在python中使用class关键字创建一个类。

python 复制代码
语法格式1:
class ClassA:
    # 公共的属性
    def __init__(self):
        pass
    def fun1(self):
        pass
    def fun2(self):
        pass

语法格式2:
class ClassA(object):
    # 公共的属性
    def __init__(self):
        pass
    def fun1(self):
        pass
    def fun2(self):
        pass
        
 实例化对象的语法:
 1》无参
     对象名 = 类名()
 2》有参
     对象名 = 类名(参数列表) 

例:

python 复制代码
class Stu(object):
    id = '1001'
    name = '张三'
    def __init__(self):
        pass
    def fun1(self):
        pass

# 实例化对象
s1 = Stu()
s2 = Stu()
print(s1.name)
print(s2.name)

第一个 init()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会自动调用该方法。不是必须要定义的,可以在需要的时候再定义。

第二个 self是一个参数,表示对象自身【对象的id号】,里面存放着对象自身的地址。如果希望类中的方法可以被对象调用,第一个参数必须是self。作用是将实例对象与类的方法进行绑定,这样实例的每个对象都能调用"属于"自己的方法。传参时可以省略。

python 复制代码
class Dog(object):
    def speak(self):
        print(f"{self}在汪汪汪")

d1 = Dog()
d2 = Dog()
d1.speak()
d2.speak()

输出结果
<__main__.Dog object at 0x0000021743E82120>在汪汪汪
<__main__.Dog object at 0x0000021743E82150>在汪汪汪

2 访问属性/方法

使用符号 . 进行访问

python 复制代码
# 访问属性
对象名.属性
# 访问方法
对象名.方法名()

3.1 对象与类的关系【1】

  1. 对象拥有类的所有属性和方法
  2. 对象的属性和方法可以单独添加、删除、修改
  3. 对象与对象之间的属性和方法不可共享
  4. 对象不能独自创建,必须依托于类,类可以实例化N个对象
python 复制代码
class Stu(object):
    id = '1001'
    name = '张三'
    def fun1(self):
        pass

# 实例化对象
s1 = Stu()
s2 = Stu()
# 对象的属性可以单独修改、添加、删除
s1.name = '李四'
s1.age = 18
del s1.age
print(s1.name)
# print(s1.age)
print(s2.name)
# print(s2.age)

3.2 对象与类的关系【2】

python 复制代码
from types import MethodType

class Stu(object):
    id = '1001'
    name = '张三'

    def fun1(self):
        print(f"{self.name}会吃饭")

    def fun2(self):
        print(f"{self.name}会学习")

s1 = Stu()
s2 = Stu()
s1.name = '刘德华'
s2.name = '蔡徐坤'

s1.fun1()
s2.fun1()

def sing(self):
    print(f"{self.name}会唱歌")

def dance(self):
    print(f"{self.name}会跳舞")

# 拓展对象的方法
s1.sing = MethodType(sing, s1)
s2.dance = MethodType(dance, s2)

s1.sing()
s2.dance()

还可以使用以下函数的方式来访问属性:

  • getattr(obj, name[, default]) : 访问对象的属性。
  • hasattr(obj,name) : 检查是否存在一个属性。
  • setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
  • delattr(obj, name) : 删除属性。

4 魔方方法------构造函数 与 析构函数

  1. init 构造函数:完成对象的初始化工作,调用类创建对象时,自动执行。
  2. del 析构函数:删除对象时执行一些操作,自动执行。
  3. str 打印方法:输出执行信息,自动执行。
python 复制代码
class Car(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color

    def __str__(self):
        return f"车品牌{self.name} 颜色{self.color}"

    def __del__(self):
        print(f"{self.name}报废了,去车管所吧")


c1 = Car("奥迪", "黑色")
c2 = Car("小米su7", "紫色")

print(c1.name, c2.name)
print(c1)
print(c2)
# print(str(c1))

5 类属性/方法 与 实例对象属性/方法 与 静态方法

python 复制代码
class Student(object):
    """
    定义了一个学生类
    """
    grade = 'py24101'       # 类属性

    def __init__(self, name, age):
        self.name = name    # 实例对象属性
        self.age = age      # 实例对象属性

s1 = Student('张三', 18)

# 类属性的访问
print(Student.grade)
print(s1.grade)

# 实例属性的访问
# print(Student.name)    报错!!!
print(s1.name)
python 复制代码
class Bank(object):
    """
    定义了一个银行卡类,用于初始化、存钱、取钱
    """
    total_money = 0

    def __init__(self, name, money):
        self.name = name
        Bank.total_money += money    #改为self.

    def save(self, money):
        Bank.total_money += money

    def draw(self, money):
        Bank.total_money -= money

b1 = Bank('张三', 1000)
print(b1.total_money)
b1.save(5000)
print(b1.total_money)
b1.draw(3000)
print(b1.total_money)

b2 = Bank('李四', 8888)
print(b2.total_money)
b2.save(10000)
print(b2.total_money)

5.1 类方法、实例方法、静态方法

python 复制代码
class Student(object):
    """
    定义了一个学生类
    """
    grade = 'py24101'

    @classmethod
    def cls_fun(cls):
        """类方法中只能调用类属性和类方法"""
        print(f"班级名称是{cls.grade}")

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def fun1(self):
        """实例方法中能调用类属性、实例属性"""
        print(f"实例方法中输出类属性{self.grade}, 输出实例属性{self.name}")

    @staticmethod
    def sta_fun(x):
        print(f"{x}静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等")

s1 = Student('张三', 18)
# 如何调用类方法
Student.cls_fun()
s1.cls_fun()

# 如何调用实例方法
Student.fun1(s1)
s1.fun1()

# 如何调用静态方法
Student.sta_fun(3)
s1.sta_fun(3)

习题

python 复制代码
用面向对象实现一个信用卡取款,存款,查余额的业务,具体要求如下: 
1. 定义一个信用卡类,命名 Creditcard , 添加类属性 area,值为'中国' 
2. 添加魔法构造方法,默认值传参,对象属性及相应的默认值如下: 
开户行 bank(默认值为空字符串),存款 money(默认为0),信用额度 credit( 默认为 1000) 
3. 添加打印方法,按如下格式返回信息:XX(area)发行的XX(bank)银行 卡,现存款XX(money)元,目前可以透支XX(credit)元 
4. 添加一个进入账户的方法 enter(),无参有返。用户从键盘输入用户名和密码,当 输入与以下设置相匹配正确时账户:user 密码:200209,提醒登录成功,返回 布尔值True,否则 False,并提醒:不能使用此卡 
5. 添加往卡内存钱的方法 save(n),n 为存入的钱数。 
6. 添加提高信用额度的方法 setCredit(n),n 为新的可透支钱数。 
7. 添加付款方法 buy(n),n 为要付款的钱数。函数内完成如下功能:首先调用登录方法 enter()。登陆成功后,提示:目前可以消费的额度为XX( money 与 credit 之和)。 
9. 创建一个对象 js, 开户行为'建设银行'。调用往卡内存钱的方法,存入 2000 元打印对象 js 
10. 用提高信用额度的方法,把可透支钱数修改为 3000 运行一下付款方法 buy( 800)

6 Python的内置类属性

  • dict: 类的属性(包含一个字典,由类的数据属性组成)
  • doc:类的文档字符串
  • **name**: 类名
  • module: 类定义所在的模块(类的全名是'main.className',如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
  • bases: 类的所有父类构成元素(包含了一个由所有父类组成的元组)
python 复制代码
class Student(object):
    """
    定义一个学生类
    属性:名字 年龄
    方法:method_1 method_2
    """
    name = '张三'
    age = 18

    def method_1(self):
        pass

    def method_2(self):
        pass

print(Student.__dict__)
print(Student.__doc__)
print(Student.__name__)
print(Student.__module__)
print(int.__module__)
print(Student.__bases__)

类的封装【私有属性与方法】

  • 封装是类的三大特性之一。
  • 封装指的是隐藏对象中一些不希望让外部所访问的属性或方法。
  • python中封装其实是通过设置访问权限来体现的,私有属性和私有方法是控制访问权限的组成部分

1. 私有属性

在类的内部使用,不希望外部直接访问的变量。

在python中,使用双下划线作为前缀来定义私有属性。

私有属性在类外不能访问

python 复制代码
class Bank(object):
    """
    定义了一个银行卡类
    属性:name     pwd密码【我不希望外部访问】
    """
    def __init__(self, name, pwd):
        self.name = name
        self.__pwd = pwd

    # 为了在某些需要的时候,访问到私有属性,所以需要在类内部设置两个接口
    def get_pwd(self):
        return self.__pwd

    def set_pwd(self, newpwd):
        self.__pwd = newpwd


# print(Bank.__pwd)

b1 = Bank('张三', '123456')
print(b1.name)
# print(b1.__pwd)
print(b1.get_pwd())
b1.set_pwd('666888')
print(b1.get_pwd())

2. 私有方法

和私有属性是一样的。

python 复制代码
class Bank(object):
    """
    定义了一个银行卡类
    属性:name     pwd密码【我不希望外部访问】
    """
    def __init__(self, name, pwd):
        self.name = name
        self.__pwd = pwd

    def __info(self):
        print(f"名字{self.name}, 密码{self.__pwd}")

    def get_info(self):
        self.__info()

# Bank.__info() 报错
b1 = Bank('李四', '123456')
# b1.__info()   报错
b1.get_info()

3. 属性装饰器

属性装饰器是实现把方法转为属性的装饰器。

作用:

  1. 把方法转为属性,便于操作属性
  2. 实现对属性的更改(验证)、查看、删除

语法格式:

python 复制代码
语法格式:
class 类名(object):
    def __init__(self):
        self.__名字 = xxx
    
    @property
    def 函数名(self):
        return self.__名字
    
    @函数名.setter
    def 函数名(self, m):
        self.__名字 += m
python 复制代码
class Car(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color
        self.__num = 20

    @property
    def num(self):
        return self.__num

    @num.setter
    def num(self, x):
        self.__num += x

c1 = Car('法拉利', '红色')
print(c1.name, c1.color, c1.num)
c1.num = 80
print(c1.num)
python 复制代码
class Student(object):
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, new_name):
        if not isinstance(new_name, str):
            print('名字必须是一个字符串')
        else:
            self.__name = new_name

    @name.deleter
    def name(self):
        print("已删除名字")
        del self.__name

s1 = Student('张三')
print(s1.name)
s1.name = 111
s1.name = '华清远见'
print(s1.name)
del s1.name

类的继承

面向对象的编程带来的主要好处之一就是代码的重用,实现这种重用的方法之一就是通过继承机制。

通过继承创建的新类称之为【子类】或者【派生类】,被继承的类称之为【父类】、【基类】、【超类】。

1. 继承语法格式

python 复制代码
class  子类名(父类名列表):
    pass

例子
class Parent(object):
    """
    定义父类
    """
    par_attr = 100

    def __init__(self):
        print("初始化父类")

    def par_fun1(self):
        print("父类方法1")

    def par_fun2(self):
        print("父类方法2")

class Child(Parent):
    """
    定义子类
    """
    child_attr = 666
    def __init__(self):
        print("初始化子类")

    def child_fun1(self):
        print("子类方法1")

c1 = Child()
print(c1.child_attr)
c1.child_fun1()

print(c1.par_attr)
c1.par_fun1()
c1.par_fun2()

2. 多继承语法【明白即可,不建议乱用】

如果在继承的元组()里面有一个以上的类,就称之为多继承。

python 复制代码
class A:
    pass

class B:
    pass

class C:
    pass

class D(A, B, C):
    pass

d1 = D()
print(D.mro())
# python中提供了一个函数mro()用于查看继承的顺序。

3. 继承重写父类方法

如果你的父类方法不能满足你得要求,你可以在之类中重写父类的方法

python 复制代码
class Parent(object):
    def method(self):
        print(f"{self}的方法")

class Child(Parent):
    pass

c = Child()
c.method()


# 重写
class Parent(object):
    def method(self):
        print(f"{self}的方法")

class Child(Parent):
    def method(self):
        print("xxxxxxxxxx")
        print(f"{self}的方法")

c = Child()
c.method()

这里列出了一些通用的功能,可以在自己的类重写:

  1. init ( self [,args...] ) 构造函数 简单的调用方法: obj = className(args)
  2. del( self ) 析构方法,删除一个对象 简单的调用方法 : del obj
  3. repr( self ) 转化为供解释器读取的形式 简单的调用方法 : repr(obj)
  4. str( self ) 用于将值转化为适于人阅读的形式 简单的调用方法 : str(obj)
  5. cmp ( self, x ) 对象比较 简单的调用方法 : cmp(obj, x)

4. python继承特点

  • 在子类中如果需要父类的构造方法,需要显式调用父类的构造方法,或者不重写父类的构造方法。init()
  • 在子类中调用父类的方法,需要显式调用,且第一个参数self不能省略。
python 复制代码
class Parent(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def method(self):
        print(f"{self}的方法")

class Child(Parent):
    def fun1(self):
        print(self.x , self.y)
# 不重写父类构造方法
c = Child(1, 2)
c.fun1()
python 复制代码
class Parent(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def method(self):
        print(f"{self}的方法")

class Child(Parent):
    def __init__(self, x, y, z):
        Parent.__init__(self, x, y)
        self.z = z

    def fun1(self):
        print(self.x , self.y, self.z)

# 重写父类构造方法、里面显式调用父类构造方法
c = Child(1, 2, 33)
c.fun1()
python 复制代码
class Parent(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Child(Parent):
    def __init__(self, x, y, z):
        super().__init__(x, y)
        self.z = z

    def add(self):
        return self.x + self.y + self.z

c = Child(1, 1, 1)
print(c.add())
python 复制代码
class Parent(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def add(self):
        return self.x + self.y

class Child(Parent):
    def __init__(self, x, y, z):
        super().__init__(x, y)
        self.z = z

    def add(self):
        return super().add() + self.z

c = Child(1, 1, 1)
print(c.add())

5. 运算符重载

在Python中,并没有像其他语言(如C++)中那样的内置机制来重载运算符。但是,你可以通过定义特定的方法来模拟运算符重载的行为。

以下是一些常见运算符以及它们对应的特殊方法:

加法:+ 对应 add

减法:- 对应 sub

乘法:* 对应 mul

除法:/ 对应 truediv

取模:% 对应 mod

幂运算:** 对应 pow

位运算:<< 对应__lshift__

位运算:>> 对应 rshift

位运算:& 对应 and

位运算:| 对应 or

位运算:^ 对应 xor

python 复制代码
class Operator(object):
    def __init__(self, x):
        self.x = x

    def __add__(self, other):
        return self.x + other.x * 3

o1 = Operator(1)
o2 = Operator(3)
print(o1 + o2)
python 复制代码
class Operator(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return self.x * other.x + self.y * other.y

o1 = Operator(1, 2)
o2 = Operator(3, 4)
print(o1 + o2)

6. 类的多态

python中的多态也可以通过方法重写进行。

同一个方法,不同对象显式的结果不同。

python 复制代码
class Animal(object):
    name = '动物'
    age = 0
    def speak(self):
        print("动物的声音")

class Dog(Animal):
    def speak(self):
        print("汪汪汪")

class Cat(Animal):
    def speak(self):
        print("喵喵喵")

a = Animal()
d = Dog()
c = Cat()

a.speak()
d.speak()
c.speak()

7. 关于下划线说明

  1. foo: 以双下划线开头双下划线结尾,定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的,自动。
  2. _foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import ···
  3. __foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

8. 简单练习题

python 复制代码
1. 创建一个类Circle,具有radius实例属性
编写打印方法,返回属性值
编写实例方法,输出圆的面积
编写析构方法,输出"圆的半径不能为负数"
2. 定义一个狗类Dog
类属性:狗品种breed
定义一个有参的构造方法:有狗姓名name,狗年龄age两个实例属性
定义一个打印方法:返回'[name]、[age] the [breed] is barking!'
定义一个析构方法:输出我是析构方法
实例化一个对象调用打印方法
3. 要求设计一个学生类Student
类属性学校school,默认值为华清远见
属性有:姓名、html成绩、JavaScript成绩、python成绩
添加打印方法输出完整的学生信息
添加类方法用来修改类属性的值
添加求学生总分的方法
添加求学生平均分的方法
实例化一个学生对象,调用所有方法
4. 定义一个Person类
定义一个类属性:国家,默认值为:中国
定义一个构造方法:设置姓名,年龄属性
定义一个静态方法,功能描述:输出"我们都是中国人"
定义一个类方法,用来获取类属性值
定义一个类方法,用来修改类属性值
定义一个打印方法,输出所有属性值
实例化一个对象调用所有方法
5. 有一个计算器类,具有运算功能,能对两个整数进行相加运算
有一个闹钟类,具有闹铃功能,能发出"懒猪起床"的声音
有一个手机类,需要同时拥有运算功能和闹铃功能,实现多继承
实例化一个手机类的对象,测试继承的两个功能
6. 定义名为Fruit的类
编写构造方法,接收1个外部参数color
编写打印方法,返回属性值
编写Fruit的子类Apple,定义方法setColor,给color赋值
实例化子类对象,调用setColor方法
7. 定义一个商品类 
在构造方法中添加以下属性:ball_name(球类名称)、price(球类价格)、 number(存球数量,默认值为 100),
使用传参的方式对实例属性进行赋值 
添加一个打印方法,格式化输出"球类:XXX(ball_name),价格:XX(price),目前存 球数量:XXX(number)" 
添加一个析构方法,打印输出"本店已打烊,欢迎下次再来!" 
添加一个实例方法 borrow,功能实现将存球数量减 5,并显示当前存球量 
添加一个实例方法 restore(n),功能实现将存球量加 n,并显示当前存球量 
添加一个实例方法 set_price(m),返回修改后球的价格 
添加一个实例方法 get_number,如果存球量大于 100,则返回"本店将要打折处理 库存球",如果存球量小于 50,则返回"本店将要购买一批新球",其他则返回"正常营 业!"
创建一个对象:bl = Ball("篮球",108,50) 
循环调用 borrow 方法直到存球量<=0 时,当存球量为 0 时,输出"库存归 0, 请及时补充库存" 
调用测试所有的实例方法

8. 进阶练习题

python 复制代码
请实现一个名为 BankAccount 的银行账户类,该类具有以下特征:
1. 私有属性:balance,表示账户余额。
2. 私有方法:transaction(),该方法接受一个正或负的数值,表示账户的一笔交易,将其加入余额。
3. 公共方法:deposit(amount),将给定的金额加入余额。
4. 公共方法:withdraw(amount),从余额中减去给定的金额。
5. 公共方法:get_balance(),返回当前余额。
实例化对象,进行测试


需求:设计一个购物车系统,实现以下功能: 
1. 用户可以浏览商品列表,每个商品包括商品名称、价格和库存数量。 
2. 用户可以将商品添加到购物车中,可以添加多个同一商品。 
3. 用户可以从购物车中移除商品,可以移除多个同一商品。 
4. 用户可以查看购物车中所有商品的名称、价格、数量和总价。 
5. 用户可以根据需要修改购物车中商品的数量。 
6. 用户可以提交订单并付款。 
分析:根据以上需求,我们可以设计以下类: 
商品类 Product: 
    属性:商品名称、价格、库存数量。 
    方法:展示商品信息。 
购物车类 ShoppingCart: 
    属性:商品列表。 
    方法:添加商品、移除商品、修改商品数量、展示购物车信息、计算总价。 
订单类 Order:
    属性:订单编号、购买商品列表、购买时间、总价。 
    方法:生成订单、付款。 
用户类 User: 
    属性:购物车、订单列表、账户余额。 
    方法:浏览商品列表、将商品添加到购物车、从购物车中移除商品、修改购物车中商品数量、查看购物车信息、提交订单、付款。 
实例化对象,进行测试
python 复制代码
1.创建学生类Person。
2.添加静态方法,showInfo:
(1)显示信息"龙的传人";
3.添加类属性:country,国籍,默认值为"中国"。
4.添加类属性:nation,民族,默认值为"汉族"。
5.添加构造方法,添加如下对象属性:
(1)name,保存学生姓名,默认值为空字符串。
(2)age,保存学生年龄,默认值为0。
(3)birth,保存出生日期,默认值为空字符串。
(4)money,保存工资收入,私有权限,默认值为0。
6.添加类方法,获取两个类属性的值。
7.添加魔法方法,将所有属性用格式化字符串组合成一个字符串后返回。
(1)格式如下:
    国籍:中国
    民族:汉
    姓名:XXX
    年龄:XXX
    出生日期:XXX
8.添加setName方法,修改对象属性name。
9.添加getName方法,获得对象属性name的值。
10.添加返回age值的方法getAge,利用属性装饰器修饰该方法,并对age值进行修改。
11.添加setBirth方法,修改对象属性birth。
12.添加getBirth方法,获得对象属性birth的值。
13.添加私有属性money的set和get方法。
14.添加对象方法info,输出当前对象的个人信息:
(1)格式如下:姓名---年龄---出生日期---存款
15.添加主程序入口,完成如下任务:
(1)调用静态方法:
     ①提示:通过对象调用
     ②提示:通过类名调用;
(2)创建一个对象。
(3)修改对象的所有对象属性。
(4)通过对象方法获得对象的所有属性值,并显示。
(5)调用info显示对象信息。
(6)调用对象的打印方法,输出信息;
(7)再次修改所有对象的属性。
(8)再次调用对象的打印方法。
相关推荐
前端每日三省2 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
好看资源平台11 分钟前
网络爬虫——综合实战项目:多平台房源信息采集与分析系统
爬虫·python
凡人的AI工具箱15 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
chnming198731 分钟前
STL关联式容器之map
开发语言·c++
进击的六角龙33 分钟前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂33 分钟前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
湫ccc40 分钟前
Python简介以及解释器安装(保姆级教学)
开发语言·python
孤独且没人爱的纸鹤43 分钟前
【深度学习】:从人工神经网络的基础原理到循环神经网络的先进技术,跨越智能算法的关键发展阶段及其未来趋势,探索技术进步与应用挑战
人工智能·python·深度学习·机器学习·ai
程序伍六七44 分钟前
day16
开发语言·c++
羊小猪~~1 小时前
tensorflow案例7--数据增强与测试集, 训练集, 验证集的构建
人工智能·python·深度学习·机器学习·cnn·tensorflow·neo4j