打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Python基础——面向对象基础(练习)_python面向对象练习

文章目录

    • 一、定义
      • 1、简介
      • 2、面向对象的三个特征
    • 二、面向对象的基本语法
    • 三、对象的属性
    • 四、self的指向
    • 五、魔法方法
    • 六、==
      • 1、==
      • 2、比较两个对象的大小
      • 3、给对象排序
    • 七、面向对象的练习
      • 1、小明体重
      • 2、房子户型、家具
      • 3、士兵分配枪
      • 4、点是否在线上
      • 5、点是否在矩形内

一、定义

1、简介

面向对象编程:OOP
面向对象编程的关注点在于谁来做,相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
属性、行为
先有类,把具体的东西抽象并归类,然后根据类再生产出一个个对象
类:是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用

  • 特征其实就是一个变量,在类里称之为属性;
  • 行为其实就是一个函数,在类里称之为方法;
  • 类其实就是由属性和方法组成的一个抽象概念

2、面向对象的三个特征

封装、继承、多态

二、面向对象的基本语法

# 有两个对象:
# 小明今年23岁,身高180cm,体重75kg,它能够睡觉
# 小红今年21岁,身高170cm,体重58kg,它能够睡觉


# 创建一个类,并且定义一个类名
class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

    def sleep(self): # 行为
        print('正在睡觉!')


# 使用Person类创建了一个Person对象 p1
p1 = Person('小明', 23, '180cm', '75kg')
p1.sleep()

p2 = Person('小红', 21, '170cm', '58kg')
p2.sleep()

三、对象的属性

  • 使用 点 . 语法,可以给一个对象添加属性;
  • python 里支持动态属性(尽量避免使用动态属性);
  • 对象在创建的时候,可以不设置属性,创建好了以后,再手动的给对象添加属性(动态添加属性);
  • __init__方法要求对象创建的时候就必须要有某些属性
class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

    def say_hello(self):
        print('大家好,我的名字是{},我{}岁了'.format(self.name, self.age))
        # print('大家好,我的名字是{},我{}岁了'.format(self.name, self.money) # 会报错,因为money属性是后面手动动态添加的


# __init__ 方法要求对象创建的时候就必须要有某些属性
s1 = Student('jerry', 18, 100)
print(s1.name)

print(s1.addr)   # 会报错,因为没有addr属性,AttributeError: 'Student' object has no attribute 'addr'

# 对象创建好了以后,还可以随时动态的添加属性
s1.money = 1000
print(s1.money)

print(s1.age)  # 18
s1.age = 20
print(s1.age)  # 20

s1.say_hello() # 会成功打印,如果print中有动态属性,会报错

s2 = Student('chris', 20, 98) 
s2.say_hello() # 会成功打印

四、self的指向

  1. 会调用 Dog 类的 __new__方法,申请一段内存空间
  2. 把 __init__里的 self 指向这一段内存空间
  3. 调用 __init__方法,在内存里放入自己的数据
  4. 把这段内存空间赋值给变量 d1,即最后d1也会指向这一段内存空间
  5. self只能在__init__中使用
class Dog(object):
    def __init__(self, name, color):
        self.xingming = name
        self.yanse = color

    def say_hello(self):  # 谁调用这个方法,self指的就是谁
        print('大家好,我是{}'.format(self.xingming))

d1 = Dog('大黄', '白色')
print(d1.yanse)
d1.say_hello() # d1调用了say_hell0()方法,self指的就是d1,self.xingming指的就是d1的姓名'大黄’

d2 = Dog('旺财', '黑色')
d2.say_hello()

五、魔法方法

在类里,以__开始,并且以__结束的方法,我们称之为魔法(魔术方法)
特点: 不用手动的调用,它们会在适当的时机自动调用

  • __str__方法必须要有返回值,而且是一个字符串;当一个对象要变成字符串的时候会自动调用;
  • __repr __当需要修改一个对象的输出结果时候
  • __del__当一个对象被销毁的时候,会自动调用这个方法
class Person(object):
    def __init__(self, name, age):
        print('__init__函数被调用了!!!!')
        self.name = name
        self.age = age

    def __str__(self):
        # 当一个对象要变成字符串的时候会自动调用
        # __str__ 方法必须要有返回值,而且是一个字符串
        print('__str__被调用了!!!!!')
        # return 'hehe'
        return 'name:' + self.name + ', age:{}'.format(self.age)

    def __repr__(self):
    	# 当需要修改一个对象的输出结果时候
        return 'name:' + self.name + ', age:{}'.format(self.age)
		return 'yes'
		
    def __del__(self):
        # 当一个对象被销毁的时候,会自动调用这个方法
        print('hehehehe')
        del self

    def sleep(self):
        print('{}正在睡觉'.format(self.name))

p1 = Person('jerry', 18) # 自动被调用,会打印'__init__函数被调用了!!!!'
# print(p1)  # <__main__.Person object at 0x0069F7D0>
print(p1)  # {name:jerry,age:18}

六、==

1、==

  • 两个对象做 == 比较,会调用对象的 __eq__方法;
  • 如果不修改__eq__方法,两个对象 == 默认也是比较内存地址
  • 列表==比较的是内容,is比较的是内存地址
  • 对象==若不修改eq方法,默认比较的也是内存地址
# 1、
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person('zhangsan', 18)
p2 = Person('zhangsan', 18)

print(p1 == p2) # False,对象==若不修改eq方法,默认比较的是内存地址
print(p1 is p2) # False

n1 = ['zhangsan', 'lisi', 'wangwu']
n2 = ['zhangsan', 'lisi', 'wangwu']
print(n1 == n2)  # True,列表==比较的是内容,is比较的是内存地址
print(n1 is n2)  # False
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        # if self.name == other.name and self.age == other.age:
        #     return True # 如果name和age都一样的话,就返回true,否则返回false
        # return False
        return self.name == other.name and self.age == other.age  # 等价


p1 = Person('张三', 18)
p2 = Person('张三', 18)

p3 = p2 # python的赋值是内存地址的赋值,即把p2的地址给了p3,指向同一块内存地址,p3没有创建新的对象,创建对象的格式如p1,p2
print(p3 is p2)  # True
print(p3 is p1)  # False

print(p1 == p2)  # True,修改了eq方法,如果name和age都一样的话,就返回true
# p1 == p2 ==> p1.__eq__(p2)即p1==p2即p1调用的eq方法

print(p1 is p2)  # False

2、比较两个对象的大小

  • 默认不支持除了 == 以外的比较运算,只有重写了 __lt__或和 __gt__魔法方法以后,才支持比较运算
  • lt: less than 小于 gt: greater than 大于
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __lt__(self, other): # 重写lt方法
        return self.age < other.age


p1 = Person('chris', 18)
p2 = Person('allen', 19)

print(p1 > p2)  # False

3、给对象排序

  • 使用sort方法,参数key传入匿名函数可以对列表里的对象元素进行排序
class Person(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

    def __lt__(self, other): # 重写it方法
        # return self.age < other.age
        return self.score < other.score

p1 = Person('jerry', 18, 98)
p2 = Person('tony', 20, 81)
p3 = Person('henry', 17, 86)

persons = [p1, p2, p3]
persons.sort()

# persons.sort(key=lambda ele: ele.score),在没有it方法时(无重写的那段代码)可以把key的📄传进来

for p in persons:
    print(p.name)
# 字典排序
ps = [
    {'name': 'zhangsan', 'age': 18},
    {'name': 'lisi', 'age': 19},
    {'name': 'wangwu', 'age': 17},
    {'name': 'zhaoliu', 'age': 20},
    {'name': 'tianqi', 'age': 16},
    {'name': 'wangba', 'age': 21}
]

# def demo(ele): # 会不断地把一个个字典传进来,给参数ele
#     return ele['age']
# ps.sort(key=demo)
 
ps.sort(key=lambda ele: ele['age']) # 可以用lambda表达式简写
print(ps)

七、面向对象的练习

1、小明体重


# 1、小明体重 75.0 公斤,小明每次跑步会减肥 0.5 公斤,小明每次吃东西体重增加 1 公斤。
# 在打印小明这个对象时,输出小明的姓名,体重信息

class Person(object):
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight

    def run(self):
        self.weight -= 0.5

    def eat(self):
        self.weight += 1

    def __int__(self): # 魔法方法
        return 100

    def __float__(self): # 魔法方法
        return 34.5

    def __str__(self):  # 魔法方法,在需要返回一个字符串时,自动调用该魔法方法
        return '姓名:{},体重{}kg'.format(self.name, self.weight)


p1 = Person('小明', 75)
p1.run()
p1.run()
p1.run()
p1.eat()
p1.run()

print(p1)
print(str(p1))
print(int(p1))
print(float(p1))

2、房子户型、家具

# 2、房子(House)有户型、总面积、剩余面积和家具名称列表属性
# 新房子没有任何的家具
# 将家具的名称追加到家具名称列表中
# 判断家具到面积是否超过剩余面积,如果超过,提示不能添加这件家具;
# 家具(HouseItem)有名字和占地面积属性,其中
# 席梦思(bed)占地4平米
# 衣柜(chest)占地2平米
# 餐桌(table)占地1.5平米
# 将以上三件家具添加到房子中
# 打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表

class House(object):
    def __init__(self, type, total_area):
        self.type = type
        self.total_area = total_area
        self.free_area = total_area * 0.5
        self.item_list = [] # 给一个空列表

    def add_item(self, item):
        if self.free_area < item.area * 1.5: # 假设家具占地面积乘以1.5为实际占地面积
            print('已经放不下了!')
            return # 如果放不下后,return后,之后到代码便不会再走了

        self.item_list.append(item.name) # 如果还有剩余面积,往里面添加
        self.free_area -= item.area * 1.5

    def __str__(self):
        return '户型{},总面积{},剩余面积{},家具列表{}'.format(self.type, self.total_area, self.free_area, self.item_list)


class HouseItem(object):
    def __init__(self, name, area):
        self.name = name
        self.area = area


h1 = House('一居室', 20)

bed = HouseItem('席梦思', 4)
chest = HouseItem('衣柜', 2)
table = HouseItem('餐桌', 1.5)

h1.add_item(bed)
h1.add_item(chest)
h1.add_item(table)

print(h1)

3、士兵分配枪

# 3、士兵张三有一把M416
# 枪能够装填子弹
# 枪能够发射子弹
# 如果士兵没有枪,无法开火
# 如果枪里没有子弹,需要装填子弹
# 如果有枪又有子弹,则可以开火


class Solider(object):
    def __init__(self, name, gun=None):  # 缺省参数,后续不传gun也可以
        self.name = name
        self.gun = gun

    def fire(self):
        if not self.gun:
            print('你还没有枪,不能开火!!!')
            return
        if self.gun.bullet_count == 0:
            print('没有子弹,需要装填子弹')
            return

        if self.gun.bullet_count >= 3:
            self.gun.bullet_count -= 3  # 每次开枪3连发
        else:  # 如果子弹小于3,则开火后子弹剩余0
            self.gun.bullet_count = 0
        print('有枪有子弹,开火!!!还剩{}发子弹'.format(self.gun.bullet_count))


class Gun(object):
    def __init__(self, type, bullet_count=0):  # 子弹给默认值0
        self.type = type
        self.bullet_count = bullet_count


g1 = Gun('m416', 30)
s1 = Solider('许三多')
# s1 = Solider('许三多', g1) # 实例创建时就已分配给枪
s1.gun = g1  # 如果没有该句,实例都已创建好,但是s1并没有拿到枪,即创建时没有枪,后来给了一把枪

s1.fire()

4、点是否在线上

# 定义一个类 Point,有两个属性 x,y  创建三个Point对象 a,b,c 判断c是否在ab组成的线段上
import math

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


class Line(object):  # 隐藏线索,两段线段长度加起来总和相等,即在同一条线段上
    def __init__(self, start_point, end_point):
        self.start_point = start_point
        self.end_point = end_point

    def get_length(self, point1=None, point2=None):  # 获取线段长度,即两点之间距离
        point1 = point1 or self.start_point
        point2 = point2 or self.end_point

        return math.sqrt((point2.x - point1.x) ** 2 + (point2.y - point1.y) ** 2) # 开方,math模块

    def is_inline(self, point):  # 判断点是否在线上
        return self.get_length() == self.get_length(self.start_point, point) + self.get_length(self.end_point, point)


p1 = Point(3, 3)
p2 = Point(6, 6)  
p3 = Point(6, 7)  # false该点不在线上
p4 = Point(9, 9)  # true该点在线上

l = Line(p1, p2)
print(l.get_length())  # 如果什么参数也不传,则point1取默认值None,为false,则继续取or后面的值self.start_point,or一直取到第一个为true的值
# print(l.get_length(p1, p3))  # p1传给point1,p3传给point2
print(l.is_inline(p4))

5、点是否在矩形内

定义一个类React,有start_x,start_y,width,height的属性,表示矩形的长和宽。判断(x,y)是否在矩形的范围内

# 1、
class React(object):

    def __init__(self, start_x, start_y, width, height):
        self.start_x = start_x
        self.start_y = start_y
        self.width = width
        self.height = height

    def is_inside(self, x, y):
        # if self.start_x < x < self.start_x + self.width and self.start_y < y < self.start_y + self.height:
        #     return True
        # return False
        return self.start_x < x < self.start_x + self.width and self.start_y < y < self.start_y + self.height


r = React(4, 5, 10, 6)
print(r.is_inside(20, 25))  # False
print(r.is_inside(12, 9))  # True
# 2、再多加一个point类

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

class React(object):
    def __init__(self, start_point, width, height):
        self.start_point = start_point
        self.width = width
        self.height = height

    def is_inside(self, point):
        return self.start_point.x < point.x < self.start_point.x + self.width and self.start_point.y < point.y < self.start_point.y + self.height

sp = Point(10, 18)  # 实例化矩形的起始点:start_point(即start_x,start_y)
r = React(sp, 20, 25)

p = Point(22, 28)
print(r.is_inside(p))  # True

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
python 面向对象全面详解
Python深入学习之对象的属性
Python第五篇:类与对象 找对象不积极,思想有问题
从 Zero 到 Hero ,一文掌握 Python
面向对象(一)
python笔记58-类里面的__dict__属性
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服