Python高级培训:类和对象

Python高级培训:类和对象

第一讲

什么是面向对象

对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例

方法: 类中定义的函数

实例化: 创建一个类的实例,类的具体对象

类的定义

类定义的语法格式:

class ClassName(object):
    <statement-1>
    .
    .
    .
    <statement-N>

类的对象

类对象支持两种操作:属性引用和实例化
属性引用的标准语法:obj.name

实例化的例子:将一个类赋给一个变量这样的操作称为实例化类

x = MyClass()

类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用

当然, __init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上。

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i)   # 输出结果:3.0 -4.5

self代表类的实例而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,它的名称一般是 self

class Test:
    def prt(self):
        print(self)
        print(self.__class__)
 

类的方法

在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
# 实例化类
p = people('runoob',10,30)
p.speak() # 输出结果为“runoob 说: 我 10 岁。”

类的继承

子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。

单继承

使用super的单继承

超类super(class,self) 首先找到 class 的父类,然后把类class的对象转换为其父类的对象

class FooParent(object):
    def __init__(self):
        self.parent = 'I\'m the parent.'
        print ('Parent')
    
    def bar(self,message):
        print ("%s from Parent" % message)
 
class FooChild(FooParent):
    def __init__(self):
        # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象
        super(FooChild,self).__init__()    
        print ('Child')
        
    def bar(self,message):
        super(FooChild, self).bar(message)
        print ('Child bar fuction')
        print (self.parent)
 
if __name__ == '__main__':
    fooChild = FooChild()
    fooChild.bar('HelloWorld')

不使用super的单继承

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
 
 
s = student('ken',10,60,3)
s.speak()

多继承

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
 
#另一个类,多重继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
 
#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中参数位置排前父类的方法
# 输出结果为“我叫 Tim,我是一个演说家,我演讲的主题是 Python”

多态

字面意思是一种事物的多种形态,其实是一个方法可以有多种不同的功能

例如猫可以吃饭,狗可以吃饭,老鼠可以吃饭,人也可以吃饭,多态的作用就在于从人可以吃饭到“动物”可以吃饭的转变。

# animals父类定义
class animals(object):
    # 类属性定义
    name = 'animals'

    # 构造函数定义
    def __init__(self):
        pass

    # 类方法定义
    def eat(self):
        print(self.name+'可以吃饭')

# Cat子类定义
class Cat(animals):

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

# Human子类定义
class Human(animals):

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

# Dog子类定义
class Dog(animals):

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


# eat函数实现eat方法的多态
def eat(obj):
    obj.eat()


# 实例化对象
doglas = Dog('dog')
tom = Cat('cat')
hjh = Human('human')
# 多态演示
eat(doglas)
eat(tom)
eat(hjh)
# 输出为
'''
dog会吃饭
cat会吃饭
human会吃饭
'''

类属性和对象属性

类属性是在类中定义的属性

对象属性是在构造函数中定义的属性

例如:

class Person(self):
	# 类属性定义
	name = 'hjh'
	'''
	'''
	age = '19'
	# 构造函数定义
	def __init__(self, name, age):
		# 对象属性定义
		self.name = name
		self.age = age
		
	# 类方法定义
	'''
	'''
  1. 对象属性的优先级高于类属性

    ​ 在类名与对象名相同时优先调用对象属性

    ​ 当调用到了不存在的对象属性就转而调用对应的类属性

  2. 给某一对象添加的属性只针对当前对象生效

  3. 类属性与对象属性可以进行增添和删改

    per.name = 'hjh'或者del per.name

  4. 对象名尽量不要和类名相同

第一次作业

1、选择小汽车和客车为对象,使用类实现它们的属性和方法(汽车的重量属性,驾驶的方法),并打印属性

# 小汽车为对象
class Car(object):
    # 属性定义
    name = 'Tesla FSD'
    manufactureData = '2022.1.3'
    weight = '650kg'
    color = '黑白相间'
    driveMethod = '自动驾驶'
    owner = '*'
    buytime = '*'
    price = '1 million $'

    # 构造函数定义
    def __init__(self, owner, buytime):
        self.owner = owner
        self.buytime = buytime

    # 方法定义
    def date(self):  # 通过date方法打印属性
        print("Car的生产日期:%s\n车主:%s\n购买时间:%s\n价格:%s\n车型:%s\n重量:%s\n颜色:%s" % (
            self.manufactureData, self.owner, self.buytime, self.price, self.name, self.weight, self.color))


# 客车为对象
class Passengercar(object):
    # 属性定义
    name = 'Zk6119'
    manufactureData = '2022.1.3'
    weight = '1500kg'
    color = '红色'
    driveMethod = '手动驾驶'
    price = '50 million $'

    # 构造函数定义
    def __init__(self, owner, buytime):
        self.owner = owner
        self.buytime = buytime

    # 方法定义
    def date(self):  # 通过date方法打印属性
        print("Passenger Car的生产日期:%s\n车主:%s\n购买时间:%s\n价格:%s\n车型:%s\n重量:%s\n颜色:%s" % (
            self.manufactureData, self.owner, self.buytime, self.price, self.name, self.weight, self.color))


print("*********************************************")
c = Car('hjh', '2022.1.4')  # 实例化Car对象
print(c.date())  # 使用date方法打印属性
print("*********************************************")
p = Passengercar('hjh', '2022.1.4')  # 实例化Passengercar对象
print(p.date())  # 使用date方法打印属性
print("*********************************************")

2、对第一个问题改写:继承客车的属性和方法,改造为公交车,输入的名字为:“东风路28路公交车”,并打印(也包括属性和驾驶的方法)

# 创建父类客车对象
class Passengercar(object):
    # 属性定义
    name = 'Zk6119'
    manufactureData = '2022.1.3'
    weight = '1500kg'
    color = '红色'
    driveMethod = '手动驾驶'
    price = '50 million $'

    # 构造函数定义
    def __init__(self, owner, buytime):
        self.owner = owner
        self.buytime = buytime

    # 方法定义
    def date(self):  # 通过date方法打印属性
        print("Passenger Car的生产日期:%s\n车主:%s\n购买时间:%s\n价格:%s\n车型:%s\n重量:%s\n颜色:%s" % (
            self.manufactureData, self.owner, self.buytime, self.price, self.name, self.weight, self.color))


# 创建东风路28路公交车为对象继承客车对象的属性和方法
class Bus28(Passengercar):
    # 属性定义
    # # 已从父类继承
    # 构造函数定义
    def __init__(self, name, owner, buytime):
        # 调用父类的构造函数
        Passengercar.__init__(self, owner, buytime)
        self.name = name
    # 方法定义
    # # 已从父类继承


b = Bus28('东风路28路公交车', 'hjh', '2022.1.4')
print(b.date())

3、使用多态实现28路、906路、B32路公交车的驾驶方法并打印

# 创建父类客车对象
class Passengercar(object):
    # 属性定义
    name = 'Zk6119'
    weight = '1500kg'
    driveMethod = '手动驾驶'

    # 构造函数定义
    def __init__(self):
        pass

    # 方法定义
    def drivemethod(self):  # drivemethod方法打印驾驶方式
        print("%s驾驶方法:%s" % (self.name, self.driveMethod))


class No28(Passengercar):
    # 属性重定义
    driveMethod = '手动驾驶'

    # 构造函数重定义
    def __init__(self, name):
        Passengercar.__init__(self)
        self.name = name

    # 方法定义全部继承父类


class No906(Passengercar):
    # 属性重定义
    driveMethod = '远程驾驶'

    # 构造函数重定义
    def __init__(self, name):
        Passengercar.__init__(self)
        self.name = name

    # 方法定义全部继承父类


class NoB32(Passengercar):
    # 属性重定义
    driveMethod = '自动驾驶'

    # 构造函数重定义
    def __init__(self, name):
        Passengercar.__init__(self)
        self.name = name

    # 方法定义全部继承父类


# 定义drivemethod函数实现drivemethod方法的多态
def drivemethod(obj):
    obj.drivemethod()


# 实例化对象
bus1 = No28('28路公交车')
bus2 = No906('906路公交车')
bus3 = NoB32('B32路公交车')

# 利用驾驶方法打印函数实现drivemethod方法的多态
drivemethod(bus1)
drivemethod(bus2)
drivemethod(bus3)

第二讲

动态给实例添加属性和方法

给实例添加属性

例如给person添加年龄属性

person.age = '19'  # 直接给 实例名.属性名 赋值即可

给实例添加方法

不同于属性可以直接添加,方法的添加需要利用types中的MethodType方法

例如给person添加打游戏方法

# 导入MethodType方法
from types import MethodType

# 创建一个空类Human
class Human(object):
    pass

# 实例化Human对象person
person = Human()

# 创建playgame函数
def playgame(self):
    print('person会打游戏!')

# 利用MethodType方法给person实例添加playgame方法
person.playgame = MethodType(playgame, person)

person.playgame()  # 输出结果为“person会打游戏!”

类的属性保护@property

通过对动态添加属性的学习存在于类中的属性对外暴露,这样显然是不安全的因此就需要对类属性进行保护

# 使用限制访问,必须自己写get和set方法才能访问
class Person(object):
    def __init__(self, age):
        self.__age = age

    def getage(self):
        return self.__age

    def setage(self, age):
        if age < 0:
            __age = 0
        self.__age = age

per1 = Person('19')
print(per1.getage())
per1.setage('20')  # per1的age被改为"20"
print(per1.getage())
'''
输出结果为:
19
20
'''

由上面的代码可知类中的私有变量必须通过调用特定方法才能更改或抽取而不能通过先前的方式打点调用

@property可以让你对受限制访问的属性按照原先的对象名.属性名方式进行访问

class Person(object):
    def __init__(self, age):
        self.__age = age

    @property
    def age(self):  # 方法名为受限制的变量去掉双下划线
        return self.__age

    @age.setter  # 方法名去掉双下划线+setter
    def age(self, age):
        if age < 0:
            __age = 0
        self.__age = age

per1 = Person('19')
print(per1.age)  # 相当于调用了getage()
per1.age = '20'  # 相当于调用了setage()
print(per1.age)
'''
输出结果为:
19
20
'''

运算符重载

在进行运算时对于不同类型的变量会给出不同的解释,例如

v1 = 1
v2 = 2
print(v1+v2)
v1 = '1'
v2 = '2'
print(v1+v2)
'''
输出结果为:
3
12
'''

同样的当对象在进行运算时也会给出特别的解释,例如

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b
 
   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)  # 发现有print执行 __str__(),返回'Vector(7, 8)'
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)  # 发现有运算符'+'执行__add__(),返回Vector(7, 8)
 
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
'''
输出结果为:
Vector(7, 8)
'''

总结:

两个对象之间的运算符相当于触发器,例如两个对象的’+'运算会触发__add__()方法

对象1 + 对象2的结果等价于对象1.__add__(对象2)

以下是常见的对象运算

image-20220106140234228

第二次作业

1、动态给类添加方法,具体是对猫的类中没有设置奔跑的方法,在类外添加这个方法,并打印显示

# 导入MethodType方法
from types import MethodType


# 创建Cat类
class Cat(object):

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


# 书写run方法
def run(self):
    print(self.name + '可以奔跑')


dudu = Cat('嘟嘟')  # 创建对象
dudu.run = MethodType(run, dudu)  # 动态添加run方法
dudu.run()  # 调用run方法

2、在类中对__pow____lt__进行运算符重载,主要对的两个成绩进行平方运算、比较两个成绩

# 2,在类中对__pow__, __cmp__进行运算符重载,主要对的两个成绩进行平方运算、比较两个成绩
# 创建成绩类
class Grades(object):

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

    def __lt__(self, other):  # 类专有方法__lt__()由'<'触发
        if self.grades < other.grades:
            return '%s的成绩' % self.name + '<=%s的成绩' % other.name
        else:
            return '%s的成绩' % other.name + '<=%s的成绩' % self.name

    def __pow__(self, power, modulo=None):  # 类专有方法__pow__()由'**'触发
        for i in range(1, power):
            self.grades *= self.grades
        return '%s成绩的平方:%d' % (self.name, self.grades)


# 创建对象
grades1 = Grades('学生1', 600)
grades2 = Grades('学生2', 700)
# 比较两学生成绩的大小
print(grades1 < grades2)
# 打印两成绩的平方
print(grades1**2)
print(grades2**2)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值