yiruia的个人博客分享 http://blog.sciencenet.cn/u/yiruia

博文

Day 22 面向对象

已有 1393 次阅读 2020-3-19 16:36 |系统分类:科研笔记

一、初识面向对象

引入面向对象的例子:

# 人狗大战
def Person(name,blood,aggr,sex):
    person = {
        'name':name,
        'blood': blood,
        'aggr':aggr,
        'sex':sex
    }
    return person
person1 = Person('person1',100,1,'不详')
person2 = Person('person2',200,2,'不详')
# print(alex,'\n',dog)
def Dog(name,blood,aggr,kind):
    dog = {
        'name':name,
        'blood':blood,
        'aggr':aggr,
        'kind':kind
    }
    return dog
# 人的技能 打
def attack(person,dog):
    dog['blood']-= person['aggr']
    print('%s被打了,掉了%s的血'%(dog['name'], person['aggr']))

# 狗的技能 咬人
def bite(dog, person):
    person['blood'] -= dog['aggr']
    print('%s被咬了,掉了%s的血'%(person['name'], dog['aggr']))

dog1 = Dog('dog1',100,1,'teddy')
dog2 = Dog('dog2',200,2,'金毛')
bite(dog1,person1)
# print(jin,'\n',dog)

利用面向对象编写程序的优点:

代码精简了,方便增加任务,方便修改,人物更加规范

Dog函数和Person函数都是定义了一类事物,直到调用函数,赋了值才真的有了一个实实在在的人或物

代码改进:

def Person(name,blood,aggr,sex):
    person = {
        'name':name,
        'blood': blood,
        'aggr':aggr,
        'sex':sex
    }
    def attack(dog):
        dog['blood'] -= person['aggr']
        print('%s被打了,掉了%s的血' % (dog['name'], person['aggr']))
    person['attack'] = attack
    return person

def Dog(name,blood,aggr,kind):
    dog = {
        'name':name,
        'blood':blood,
        'aggr':aggr,
        'kind':kind
    }

    def bite(person):
        person['blood'] -= dog['aggr']
        print('%s被咬了,掉了%s的血' % (person['name'], dog['aggr']))
    dog['bite'] = bite
    return dog

alex = Person('alex',100,1,'不详')
jin = Dog('狗剩',100,1,'teddy')
print(jin)
jin['bite'](alex)
alex['attack'](jin)

面向对象编程

类就相当于是个模子,所谓模子就是类,类是抽象的,我能直到有什么属性,有什么技能,但不能直到属性具体的值。而jin、alex就是对象,有具体的值,属性和技能都是根据类规范的。

面向对象的交互

面向过程:核心是过程(流水线思维),过程即解决问题的步骤。

        优点:极大的地降低了写代码地复杂度,只要顺着要执行地步骤,堆叠代码即可。

        缺点:一套流水线或者流程就是用来解决一个我呢提,代码牵一发而动全身。

        应用场景:一旦完成基本很少改变地场景,著名的例子有Linux内核,git,以及Apache HttP Server等。

面向函数

面向对象:面向对象的程序设计的

                 解决了程序的扩展性

                可控性差,无法向面向过程的程序设计流水线式的可以精准预测问题的处理流程与结果

                应用场景:适合复杂的编程

python中万物皆对象

比如:dict 类       d={'k':'v'}是实例化的一个对象

自定义类

    自定义函数:

        def 函数名():pass

    自定义类:

        class 类名:属性=‘a’

            print(类名.属性)

类的作用就是操作属性,查看属性。self类似一个字典,字典中可以存很多东西,self会自动作为字典返回给调用对象。

class Person: #第一步
    def __init__(self,*args): # 第二步
        print(args)

alex = Person('alex',100,1,'不详') #第三步,返回的值alex就是一个对象,调用类型加上括号就是在调用__init__方法
# __表示内置函数
class Person:
    def __init__(self,*args): # self类似一个字典,字典里可以存很多东西,self会自动作为一个字典返回给调用对象
        self.name = args[0]
        self.hp = args[1]
        self.aggr = args[2]
        self.sex = args[3]

alex = Person('alex',100,1,'不详') # alex对象,alex和self字典其实是一回事
print(alex)
print(alex.name)
print(alex.hp)
print(alex.sex)
'''
<__main__.Person object at 0x000001F984BBD3C8>
alex
100
不详
'''

对象 = 类型() 实例化

过程:

    类名()可以创造出一个对象,创造了一个self变量

    调用__init__方法,类名括号里的参数会在这里被接收

    执行__init__方法

    返回self

对象能做的事:

    查看属性

    调用方法

    __dict__,对于对象的增删改查

类名能做的事情:

    实例化

    调用方法,只不过要自己传递self参数

    调用类中的属性,也就是调用静态属性

    __dict__,类中的字典只能看不能操作

class Person:
    country = 'China' # 创造了一个只要是这个类就一定有的属性,称为类属性,也称为静态属性
    def __init__(self,*args): # 初始化方法,self是对象,是一个必须传的参数,self中只有属性
        # ,self就是一个可以存储很多属性的大字典,只不过往字典里添加属性的方式发生了一些变化
        print(self.__dict__)
        self.name = args[0]
        self.hp = args[1]
        self.sex = args[2]
        self.arrg = args[3]
        print(id(self))

    def walk(self,n): # 定义方法,self是必须传的参数一样,可以改,但是习惯性的名字就是self,且必须写在第一个,后面还可以传其他参数,是自由的
        print('%s gogogo,go了%s步'%(self.name,n))
alex = Person('狗剩',100,'女',200) # 类名还可以实例化对象
print(alex.name) # 对象可以查看属性
print(id(alex)) # alex和self是同一内存地址
# print(Person.__dict__)
Person.walk(alex,5) #调用方法 类名.方法名(对象名)
# ==
alex.walk(5) # 对象可以调用方法,对象.方法名就可以调用方法
print(Person.country) #静态属性,是这个类拥有的,不会随着对象的创建发生改变
# 类名可以查看类中的属性,不需要实例化就可以查看
print(Person.__dict__) #存储的类中的所有的名字
print(Person.__dict__['country']) #可以以字典的形式操作类
print(alex.__dict__) # 存储的是对象中的所有名字
alex.__dict__['name']='二哥' # 以字典的形式更改对象中的名字
print(alex.name)
# ==
alex.name = '狗剩' #一般情况下用这种方法更改对象的属性
print(alex.name)
alex.age=83
print(alex.__dict__) # 添加,和字典的操作方法类似,只是在草的过程中key不是一个字符串类型的值而是一个变量
print(alex.name)

练习

练习
class Dog:
    def __init__(self,*args):
        self.name = args[0]
        self.hp = args[1]
        self.aggr = args[2]
        self.kind = args[3]

    def bite(self,person): # person是人的实例化
        # 狗咬人,人掉血
        person.blood -= self.aggr
        # person['blood'] -= dog['aggr']
        # print('%s被咬了,掉了%s的血' % (person['name'], dog['aggr']))
class Person:
    def __init__(self,*args):
        self.name = args[0]
        self.blood = args[1]
        self.aggr = args[2]
        self.sex = args[3]
    def attack(self,dog):
        self.blood -= dog.aggr
        print('%s被攻击了,掉了%s的血' % (dog.name, self.aggr))
jin = Dog('金老板',100,20,'teddy')
alex = Person('alex',999,998,'不详')
print(jin.name)
jin.bite(alex) # ==Dog.bite(ren)
print(alex.blood)
print(jin.hp)
  • 类能够非常明显的处理一类事物,这些事物都具有相似的属性和功能

  • 当有几个函数,需要反复传入相同的参数的时候,就可以考虑面向对象

  • 这些参数都是对象的属性

class Person:
    def __init__(self,*args):
        self.name = args[0]
        self.age = args[1]
        self.sex = args[2]
    def action1(self):
        print('%s,%s岁,%s,上山去砍柴'%(self.name,self.age,self.sex))
    def action2(self):
        print(self.name,self.age,self.sex,'开车去东北')
    def action3(self):
        print(self.name,self.age,self.sex,'最爱大保健')
xiaoming = Person('小明','10','男')
xiaoming.action1()
xiaoming.action2()
xiaoming.action3()
zhang = Person('老张',90,'男')
zhang.action1()
zhang.action2()
zhang.action3()
'''
小明,10岁,男,上山去砍柴
小明 10 男 开车去东北
小明 10 男 最爱大保健
老张,90岁,男,上山去砍柴
老张 90 男 开车去东北
老张 90 男 最爱大保健
'''

circle属性 半径,两个办法:周长和面积

from math import pi
class Circle:
    def __init__(self,*args):
        self.r = args[0]
    def c(self):
        print(2*self.r*pi)
    def s(self):
        print(pi*(self.r)**2)
circle = Circle(3)
circle.c()
circle.s()
'''
18.84955592153876
28.274333882308138
'''

初识面向对象小节:

  • 定义类 class

    函数:方法、动态属性

    变量:类属性、静态属性

  • __init__方法

    初始化方法,每当我们调用类的时候就会自动触发方法,在触发这个方法之前,python帮我们创建了一个对象self,默认传self,在init方法中可以对self 赋值。

self是什么 self拥有的属性都属于对象

    在类的内部,self就是一个对象,alex = Person(),alex也是一个对象,是类外的对象,当调用类的时候自然而然就传给了self,所以说self可以更改,alex.walk == Pearson.walk(alex) self就是alex

  • 类中可以定义静态属性、定义方法,方法都有一个必须传的参数self

  • 实例化

    对象=类(参数是init方法的参数)

    实例,对象:实例和对象是一回事,完全没有区别

    对象查看属性:对象.属性名

    对象调用方法:对象.方法名(参数)

  • 类的命名空间

    类 可以定义两种属性

        静态属性

        动态属性

class Course:
    # 静态属性
    # language = 'Chinese'
    language = ['Chinese']
    # 动态属性
    def __init__(self,teacher,course_name,period,price):
        self.teacher = teacher
        self.name = course_name
        self.period = period
        self.price = price
python = Course('egon','python','six month',20000)
linux = Course('oldboy','linux','six month',20000)
# python 和linux之间是平行关系,没什么联系
python.language[0] = 'Enlish'
print(linux.language) # 输出结果为:English,对于列表而言列表里面的内容改变,不改变列表的内存地址
python.language=['English'] # 重新赋值
print(Course.language)
Course.language = 'English' #类可以改变静态变量
print(Course.language)
print(python.language,linux.language)
python.language = 'Chinese' #能改变自己空间的,不能改变类中的
print(python.language,linux.language)
print(Course.language)
'''
['Enlish']
['Enlish']
English
['English'] English
Chinese English
English
'''

图片.png

Course.name 报错,因为对象和类之间是单向联系,兑现可以用类的,但是类不能用对象的

  • 类中的静态变量可以被对象和类调用

  • 对于不可变数据类型,类变量最好用类操作,而不要用对象名操作

  • 对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的

  • 创建一个类,每实例化一个对象就记录下来,最终所有对象都可以共享数据

  • 在类中就是一个独立的命名空间,找到类之后,再没有就不能往上找了

  • 引入一个包时,就相当于类实例化一个对象,所以包会自动帮你调用一个__init__文件

class Person:
    money = 0
    def __init__(self):
        self.money += 1000
    # def work(self):
    #     Person.money += 1000
mother = Person()
father = Person()
print(mother.money)
print(father.money)

绑定方法


将方法和对象绑定在一起,当对象调用方法的时候就是把对象当成self传到方法中。

def func():pass
print(func)
class Foo:
    def func(self):
        print('func')
f1 = Foo()
print(Foo.func)
print(f1.func) # 方法和对象绑定在一起,当对象调用方法的时候就是把对象当成self传到方法中
print(f1)

组合

组合就是一个对象的属性值是另一个类的对象

class Dog:
    def __init__(self,*args):
        self.name = args[0]
        self.hp = args[1]
        self.aggr = args[2]
        self.kind = args[3]

    def bite(self,person): # person是人的实例化
        # 狗咬人,人掉血
        person.blood -= self.aggr
        # person['blood'] -= dog['aggr']
        # print('%s被咬了,掉了%s的血' % (person['name'], dog['aggr']))
class Person:
    def __init__(self,*args):
        self.name = args[0]
        self.blood = args[1]
        self.aggr = args[2]
        self.sex = args[3]
        self.money = 0
    def attack(self,dog):
        self.blood -= dog.aggr
        print('%s被攻击了,掉了%s的血' % (dog.name, self.aggr))
    def get_weapon(self,weapon):
        if self.money >=weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr
        else:
            print('余额不足,请先充值')
class Weapon:
    def __init__(self,name,aggr,njd,price):
        self.name = name
        self.aggr = aggr
        self.njd = njd
        self.price = price

    def hand18(self,person):
        if self.njd > 0:
            person.hp -= self.aggr * 2
            self.njd -= 1
alex = Person('alex',0.5,100,'不详')
jin = Dog('金老板',100,0.5,'不详')
w = Weapon('打狗棒',100,3,998)
alex.money += 1000
alex.get_weapon(w)
print(alex.weapon)
print(alex.aggr)

alex.attack(jin)
alex.weapon.hand18(jin)
print(jin.hp)

实例:求圆环的周长和面积

from math import pi
class Circle:
    def __init__(self,*args):
        self.r = args[0]
    def perimeter(self):
        return 2*self.r*pi
    def area(self):
        return pi*(self.r)**2
class Ring:
    def __init__(self,outside_r,inside_r):
        self.outside_c = Circle(outside_r)
        self.inside_c = Circle(inside_r)
    def perimeter(self):
        return self.outside_c.perimeter()+self.inside_c.perimeter()
    def area(self):
        return self.outside_c.area()-self.inside_c.area()
ring = Ring(20,10)
print(ring.area())
print(ring.perimeter())
class Teacher:
    def __init__(self,name,age,sex,bir):
        self.name = name
        self.age = age
        self.sex = sex
        self.bir = bir
class Bir:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day
b = Bir(2018,1,16)
egg = Teacher('egon',18,'女',b) # 通过Teacher属性可以拿到Bir属性
print(egg.name)
print(egg.sex)




https://blog.sciencenet.cn/blog-3405644-1224290.html

上一篇:Day21 模块的导入和异常处理
下一篇:Day23 面向对象的继承
收藏 IP: 223.91.42.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-27 01:24

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部