面向对象——类与对象篇(第一章)

Posted zsdbk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象——类与对象篇(第一章)相关的知识,希望对你有一定的参考价值。

一、什么是面向对象?

  想要学习面向对象,就要先知道面向过程。

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

    面向过程
  优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过

     程开发,性能是最重要的因素。 
  缺点:没有面向对象易维护、易复用、易扩展
    适用场景: 一旦完成很少改变的场景(著名的Linux内核、git、以及Apache HTTP Server等)

 面向对象

面向对象:面型对象的程序设计的核心是对象。

    (万物皆对象,需要关心程序中各元素(对象)的属性,及其方法) 

      比如说:

          人的属性:姓名,年龄,身高,体重

          人的技能:思考,玩耍,学习 。。。

  优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护 
  缺点:性能比面向过程低

 

认识类和对象:
简单点:

    类:具有相同特征的一类事物(人、狗、老虎)    # 都是动物类别,还可以细分位人类,狗类,虎类

    对象/实例:具体的某一个事物(对于人类来说,具体到某一个人:爱因斯坦、牛顿、等等)

 

类的创建: 

class Person:   #定义一个人类
    role = person  #人的角色属性都是人(类的静态属性)
    def walk(self):  #人都可以走路,也就是有一个走路方法,也叫动态属性(类的方法,如果有实例化对象,该对象也具有该方法)
        print("person is walking...")

 

 

类的属性引用与实例化  

   属性引用(类名.属性)

技术分享图片
class Person:   #定义一个人类
    role = ‘person‘  #静态属性
    def walk(self):  #动态属性 方法(函数) 默认带一个self参数
        print("person is walking...")

 

  查看与修改静态变量

查看静态变量的第一种方式
  print
(Person.__dict__) # 内置的双下方法   print(Person.__dict__[静态变量])
修改:   Person.
__dict__[静态变量] = 456 # 报错   print(Person.__dict__[静态变量]) 查看静态变量的第二种方式   print(Person.静态变量) # 123 值   print(Person.role)
修改:   Person.静态变量
= 456 # 正确操作   print(Person.静态变量)
删除:   
del Person.静态变量   print(Person.__dict__)

总结:

 引用静态变量
   1.类名.__dict__[‘静态变量名‘] 可以查看,但是不能删改
   2.类名.静态变量名 直接就可以访问,可以删改
   删除一个静态变量 del 类名.静态变量名
  引用动态变量
   1.类名.方法名 查看这个方法的内存地址
   1.类名.方法名(实参) 调用了这个方法,必须传一个实参,这个实参传给了self

 

  类的基本参数(补充)

一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值

二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
复制代码

 

 

对象

  实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征

class Person:
  role = ‘person‘ # 静态属性
  def __init__(self,name,sex,hp,ad):
    self.name = name # 对象属性 属性
    self.sex = sex
    self.hp = hp
    self.ad = ad
  def attack(self):
    print(‘%s发起了一次攻击‘%self.name)

alex = Person(‘a_sb‘,‘不详‘,1,5)
boss_jin = Person(‘金老板‘,‘女‘,20,50)

alex.attack() # Person.attack(alex)
boss_jin.attack() # Person.attack(boss_jin)


实例化的过程:
   1.创造一个实例,将会作为一个实际参数 # python
   2.自动触发一个__init__的方法,并且把实例以参数的形式传递给__init__方法中的self形参
   3.执行完__init__方法之后,会将self自动返回给alex
   __init__方法 :初始化方法,给一个对象添加一些基础属性的方法,一般情况下是针对self的赋值

语法:对象名 = 类名(参数)

 

  查看对象的属性与调用方法

 

print(alex.name)     #查看属性直接 对象名.属性名
print(alex.walk())   #调用方法,对象名.方法名()


对象
   在类的内部 self是本类的一个对象
   在类的外部,每一个对象都对应着一个名字,这个对象指向一个对象的内存空间
属性的调用:
   对象名.属性名 第一种调用方法
   对象名.__dict__[‘属性名‘] 第二种调用方法
方法的调用 :
   类名.方法名(对象名) # 那么方法中的self参数就指向这个对象
   对象名.方法名() # 这样写 相当于 方法中的self参数直接指向这个对象

 

 

 

 

面向对象的交互

对象可以作为参数传递给类中的方法

示例一:
class
Person: role = person # 静态属性 def __init__(self,name,sex,hp,ad): self.name = name # 对象属性 属性 self.sex = sex self.hp = hp #血量 self.ad = ad #攻击力 def attack(self,d): d.hp -= self.ad print(%s攻击了%s,%s掉了%s点血%(self.name,d.name,d.name,self.ad)) class Dog: def __init__(self,name,kind,hp,ad): self.name = name self.kind = kind self.hp = hp self.ad = ad def bite(self,p): p.hp -= self.ad print(%s咬了%s一口,%s掉了%s点血 % (self.name, p.name, p.name, self.ad))



alex = Person(‘a_sb‘,‘不详‘,1,5)     # 实例化一个人对象alex
boss_jin = Person(‘金老板‘,‘女‘,20,50)# 实例化另一个人对象
teddy = Dog(‘笨笨‘,‘teddy‘,50,10)   # 实例化一个狗对象
teddy.bite(alex)             # 狗对象向人对象发起技能
print(alex.hp)              # 打印人对象的属性
boss_jin.attack(teddy)         # 人对象向狗对象发起技能
print(teddy.hp)             # 打印狗对象的属性 

示例二:
from
math import pi class Circle: ‘‘‘ 定义了一个圆形类; 提供计算面积(area)和周长(perimeter)的方法 ‘‘‘ def __init__(self,radius): self.radius = radius def area(self): return pi * self.radius * self.radius def perimeter(self): return 2 * pi *self.radius circle = Circle(10) #实例化一个圆 area1 = circle.area() #计算圆面积 per1 = circle.perimeter() #计算圆周长 print(area1,per1) #打印圆面积和周长

 

类命名空间与对象、实例的命名空间

创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

类有两种属性:静态属性和动态属性
  静态属性就是直接在类中定义的变量
  动态属性就是定义在类中的方法

其中类的数据属性是共享给所有对象的

>>>id(egg.role)
4341594072
>>>id(Person.role)
4341594072

而类的动态属性是绑定到所有对象的

>>>egg.attack
<bound method Person.attack of <__main__.Person object at 0x101285860>>
>>>Person.attack
<function Person.attack at 0x10127abf8> 

创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性

  在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

小结

alex.name   #alex 指向我自己的内存空间 在自己的内存空间里找到name
alex.attack #alex 先找自己的内存空间 再找到类对象指针 再根据类对象指针找到类 再通过类找到attack

(1)对象的内存空间里: 只存储对象的属性,而不存储方法和静态属性 (2)方法和静态属性都存储在类的内存空间中目的:为了节省内存,让多个对象去共享类中的资源 (3)对象属性是独有的,静态属性和方法是共享的

使用类的对象可以找到两个东西?
  (1)对象所在内存空间中的储存的属性
  (2)类对象指针所指类中的所有方法和静态属性。

找寻顺序:

  (1)对象找名字的时候:先找自己内存空间中的,再找类中的。
  (2)对象没有权力修改类中的静态变量和方法
  (3)用类名去操作静态变量。
  (4)类名:实例化对象,调用静态属性,执行方法

 

 

面向对象的组合用法

组合:一个类作为另一个类的对象的属性

技术分享图片
 
 示例一:
class Weapon:
    def prick(self, obj):  # 这是该装备的主动技能,扎死对方
        obj.life_value -= 500  # 假设攻击力是500

class Person:  # 定义一个人类
    role = ‘person‘  # 人的角色属性都是人

    def __init__(self, name):
        self.name = name  # 每一个角色都有自己的昵称;
        self.weapon = Weapon()  # 给角色绑定一个武器;
        
egg = Person(‘egon‘)
egg.weapon.prick() 
#egg组合了一个武器的对象,可以直接egg.weapon来使用组合类中的所有方法
技术分享图片


圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用

技术分享图片
 
 示例二:
from math import pi

class Circle:
    ‘‘‘
    定义了一个圆形类;
    提供计算面积(area)和周长(perimeter)的方法
    ‘‘‘
    def __init__(self,radius):
        self.radius = radius

    def area(self):
         return pi * self.radius * self.radius

    def perimeter(self):
        return 2 * pi *self.radius


circle =  Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长

class Ring:
    ‘‘‘
    定义了一个圆环类
    提供圆环的面积和周长的方法
    ‘‘‘
    def __init__(self,radius_outside,radius_inside):
        self.outsid_circle = Circle(radius_outside)
        self.inside_circle = Circle(radius_inside)

    def area(self):
        return self.outsid_circle.area() - self.inside_circle.area()

    def perimeter(self):
        return  self.outsid_circle.perimeter() + self.inside_circle.perimeter()


ring = Ring(10,5) #实例化一个环形
print(ring.perimeter()) #计算环形的周长
print(ring.area()) #计算环形的面积
技术分享图片

 

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程

技术分享图片
 
 示例三:
class BirthDate:
def __init__(self,year,month,day): self.year=year self.month=month self.day=day class Couse: def __init__(self,name,price,period): self.name=name self.price=price self.period=period class Teacher: def __init__(self,name,gender,birth,course):
        self.name=name 
self.gender=gender
self.birth=birth
self.course=course
    def teach(self): 
print(‘teaching‘)
p1=Teacher(‘egon‘,‘male‘, 
BirthDate(‘1995‘,‘1‘,‘27‘),
Couse(‘python‘,‘28000‘,‘4 months‘)
)

print(p1.birth.year,p1.birth.month,p1.birth.day)

print(p1.course.name,p1.course.price,p1.course.period)
‘‘‘
运行结果:
1 27
python 28000 4 months
‘‘‘
技术分享图片

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

 

 

       








































































以上是关于面向对象——类与对象篇(第一章)的主要内容,如果未能解决你的问题,请参考以下文章

Java基础篇---复习:类与对象

第一章:基于面向对象的UML

初学者教程------JAVA面向对象篇

初学者教程------JAVA面向对象篇

初学者教程------JAVA面向对象篇

初学者教程------JAVA面向对象篇