类与对象与面向对象编程

类的定义

  • 现实世界中事物的描述、定义
  • 描述对象包含的数据和特征
  • 注意类与对象的区别

类的创建和使用

创建

  • 类名使用大驼峰命名方式,但是首字母大写,不适用下划线_
  • 实例名和模块名使用小写字母,并在单词之间加下划线_
  • 类与类之间使用2个空行分隔
  • 类的不同方法之间使用1个空行分隔
  • class ClassName():
class Dog(): #类名,大驼峰命名法
    '''
    模拟狗类动物
    '''
    def __init__(self, name, age): #构造函数,类的默认方法,前后2个双下划綫与普通方法区分
        '''
        初始化狗的name和age
        :param name:
        :param age:
        '''
        self.name = name
        self.age = age

    def sit(self):
        '''
        蹲下动作
        :return:
        '''
        print('{0} is now sitting.'.format(self.name.title()))

    def roll_over(self):
        '''
        打滚动作
        :return:
        '''
        print('{0} rolled over!'.format(self.name.title()))


__init__()构造函数

  • 创建类的实例时,自动调用
  • 形参self必不可少,且位于其他形参前面
  • 每个与类相关联的方法调用都自动传递self,它是指向实例本身的引用

__del__()析构函数

  • Python中不需要特别使用析构函数

垃圾回收器

  • gc模块collect()函数

类的方法

  • 必须有self参数
  • 调用类的方法是,可以不传递self参数

类的使用(实例化)

  • 创建对象的过程称之为类的实例化
  • 直接赋值
my_dog = Dog('willie',6)
print('My dog\'s name is {0},and it\'s {1} years old!'.format(my_dog.name,my_dog.age))
my_dog.sit()
my_dog.roll_over()

your_dog = Dog('lucy',3)
print('Your dog\'s name is {0},and it\'s {1} years old!'.format(your_dog.name,your_dog.age))
your_dog.sit()
your_dog.roll_over()

修改类中属性值

  • 1.直接修改属性值
  • 2.通过方法修改属性值
class Car():
    '''
    模拟汽车
    '''
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #为属性指定默认值

    def get_descriptive_name(self):
        '''
        输出汽车信息
        :return:
        '''
        return '{0} {1} {2}'.format(self.year,self.make,self.model).title()

    def update_odometer(self, mileage):
        '''
        更新里程数
        禁止将里程数回调
        '''
        if mileage > self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print('You can\'t roll back an odometer!')

    def increment_odometer(self, miles):
        '''
        汽车里程数增加指定的值
        禁止将里程数回调,也即禁止增加负数值
        :param miles:
        :return:
        '''
        if miles > 0:
            self.odometer_reading += miles
        else:
            print('You can\'t roll back an odometer!')

    def read_odometer(self):
        '''
        打印汽车里程数
        '''
        print('This car has {0} miles on it'.format(self.odometer_reading))


my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

my_new_car.odometer_reading = 23 #通过实例,直接修改属性值
my_new_car.read_odometer()

my_new_car.update_odometer(123) #通过方法1,修改属性值
my_new_car.read_odometer()

my_new_car.increment_odometer(100) #通过方法2,修改属性值
my_new_car.read_odometer()

关于类属性与实例属性

  • 在不对实例属性重新赋值的情况下,类属性与实力属性指向同一内存地址
  • 使用__class__.var调用类属性
class A():
    name = 'Leo'
    age = 28

    def say(self):
        self.name = 'bbb'
        self.age = 18
        print('Hi,{0}'.format(__class__.name)) #调用类属性name

print(A.name)
print(A.age)
print(id(A.name))
print(id(A.age))
a1 = A()
print(a1.name)
print(a1.age)
print(id(a1.name))
print(id(a1.age))
a1.name = 'ccc'
a1.age = 10
print(a1.name)
print(a1.age)
print(id(a1.name))
print(id(a1.age))
a1.say() #

执行结果:

Leo
28
31302744
491811136
Leo
28
31302744
491811136
ccc
10
43679392
491810560
Hi,Leo

类的继承

  • 子类继承父类时,会继承父类的所有属性和方法
  • 子类也可以定义自己特有的属性和方法
  • 父类必须包含在子类当前的文件中,且位于子类前面
  • super()特殊函数,也叫超类,代表父类,用于关联子类与父类
  • 有时需要在子类中对父类方法进行重写,此时父类中的旧方法会在调用时被忽略
  • 当一个类的属性和方法过多时,可以将其中一部分属性与方法分拆出来,定义新的类,然后可以将新类的实例化对象当做属性来赋值
  • object类是所有类的父类,也称为基类
class Car():
    '''
    模拟汽车
    '''
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #为属性'汽车里程数'指定默认值0

    def get_descriptive_name(self):
        '''
        返回汽车信息摘要
        :return:
        '''
        return '{0} {1} {2}'.format(self.year,self.make,self.model).title()

    def update_odometer(self, mileage):
        '''
        更新里程数
        禁止将里程数回调
        '''
        if mileage > self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print('You can\'t roll back an odometer!')

    def increment_odometer(self, miles):
        '''
        汽车里程数增加指定的值
        禁止将里程数回调,也即禁止增加负数值
        :param miles:
        :return:
        '''
        if miles > 0:
            self.odometer_reading += miles
        else:
            print('You can\'t roll back an odometer!')

    def read_odometer(self):
        '''
        返回汽车里程数
        '''
        print('This car has {0} miles on it'.format(self.odometer_reading))

    def fill_gas_tank(self):
        '''
        车辆充电/加油信息
        :return:
        '''
        print('Fill gas tank!')

class ElectricCar(Car): #子类ElectricCar继承父类Car
    '''
    电动汽车
    '''
    def __init__(self, make, model, year):
        '''
        初始化父类属性
        初始化电动汽车特有属性
        :param make:
        :param model:
        :param year:
        '''
        super().__init__(make, model, year) #调用父类的方法__init__(),让ElectricCar实例包含Car类的所有属性
        self.battery = Battery() #新增属性,此时会生成新的实例Battery,将新的实例作为属性赋值给self.battery,也就是说,每当创建ElectricCar实例,初始化时,会同步创建新的Battery实例


    def fill_gas_tank(self): #重写父类的方法fill_gas_tank
        '''
        电动汽车没有邮箱
        :return:
        '''
        print('This car doesn\'t need a gas tank!')

class Battery():
    '''
    模拟电动汽车的电瓶
    '''
    def __init__(self, battery_size = 70):
        self.battery_size = battery_size

    def describe_battery(self):
        print('This car has a {0} -kwh battery.'.format(self.battery_size))

    def get_range(self):
        '''
        返回续航里程
        :return:
        '''
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        print('This car go approximately {0} miles on a full charge.'.format(range))

my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())

my_tesla.fill_gas_tank()
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

导入类

  • 将类存储在模块中,在主程序中导入所需要的模块
  • import 导入
  • 高效的编程方式,不同的功能存储在不同的模块中
  • 导入模块时,先导入标准库,后导入自定义库,之间用空行分隔
import car 

my_beetle = car.Car('volkswagen','beetle',2016)
print(my_beetle.get_descriptive_name())
my_beetle.odometer_reading = 23
my_beetle.read_odometer()

my_tesla = car.ElectricCar('tesla','roadster',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

类的属性

  • 1.私有属性
    __双下划线前缀,私有属性
  • 2.公有属性【静态属性|类属性】
    没有双下划线前缀,共有属性
  • 3.实例属性
    有self前缀,实例属性
  • 4.内置属性
    __dict__
    __bases__
    __doc__
    __module__
class Fruit():
    price = 0 #类属性

    def __init__(self):
        self.color = 'red' #实例属性
        zone = 'China' #局部变量,不能被实例化对象调用
        __number = 100 #私有属性

class Apple(Fruit):
    pass

if __name__ == '__main__':
    print(Fruit.price) #返回类属性
    apple = Fruit()
    print(apple.color) #返回实例属性
    #报错 print(apple.zone)
    Fruit.price += 10
    print(apple.price)
    banana = Fruit()
    print(banana.price)
    #报错 print(banana._Fruit__number)
    print(Fruit.__dict__) #Fruit类的内置属性__dict__
    print(Fruit.__bases__) #Fruit类的内置属性__bases__
    print(Fruit.__module__) #Fruit类的内置属性__module__
    print(Fruit.__doc__) #Fruit类的内置属性__doc__

类的方法

类的内置方法

__init__    #初始化对象
__del__ #释放对象
__new__ #生成实例
__str__ #使用print时调用
__getitem__ #获取序列索引key对应的值
__len__ #使用len()时调用
__cmp   #比较两个对象
__getattr__ #获取属性值
__setattr__ #设置属性值
__delattr__ #删除属性
__getattribute__    #获取属性值
__gt__  #判断是否大于
__it__  #判断是否小于
__ge__  #判断是否大于等于
__le__  #判断是否小于等于
__eq__  #判断是否等于
__call__    #将实例作为函数调用

类的内置方法实现对象之间的运算

  • 对象之间进行关系运算,也叫运算符的重载
  • 通过类的内置方法实现,例如__gt__

类方法

  • 1.私有方法
    __双下划线前缀,私有方法
  • 2.公有方法
    没有双下划线前缀,共有方法
  • 3.静态方法
    @ staticmethod
  • 4.类方法
    @ classmethod
class Fruit():
    price = 0

    def __init__(self):
        self.__color = 'red'

    def getColor(self):   #公有方法
        print(self.__color)

    @ staticmethod #@ classmethod  静态方法/类方法
    def getPrice():
        print(Fruit.price)

    def __getPrice():
        Fruit.price += 10
        print(Fruit.price)

    count = staticmethod(__getPrice) #把__getPrice()转换为静态方法,并赋值给count,也即count()为静态方法

if __name__ == '__main__':
    apple = Fruit()
    apple.getColor()
    Fruit.count()
    banana = Fruit()
    Fruit.count()
    Fruit.getPrice()

类方法的动态特性

  • 可以将已经定义好的方法,动态添加到类中,称为新的方法
class Fruit():
    pass

def add(self):
    print('Grow...')

Fruit.grow = add #将新定义的方法add,直接动态加入到Fruit类中,重命名为grow
fruit1 = Fruit()
fruit1.grow() #调用新增加的grow方法

类的嵌套

  • Python类中可以再定义类,但是不推荐这么使用,会导致程序难以理解

抽象类

多态性

多重继承

  • 导致程序复杂,不易维护

典型案例

class Person():
    def __init__(self):
        pass

    def __setattr__(self, key, value):
        print('设置属性:{0}'.format(key))
        super().__setattr__(key,value)
        print('{0}:{1}'.format(key,value))

p = Person()
print(p.__dict__)
p.age = 18
class Person:
    # 实例方法
    def eat(self):
        print(self)
        print("Eating.....")

    # 类方法
    # 类方法的第一个参数,一般命名为cls,区别于self
    @classmethod
    def play(cls):
        print(cls)
        print("Playing.....")

    # 静态方法
    # 不需要用第一个参数表示自身或者类
    @staticmethod
    def say():
        print("Saying....")


leo = Person()

# 实例方法
leo.eat()
# 类方法
Person.play()
leo.play()
# 静态方法
Person.say()
leo.say()
class Student():
    def __init__(self, name):
        self._name = name

    def __gt__(self, other):
        print("{0}比{1}大吗?".format(self._name, other._name))
        return self._name > other._name

stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值