ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

lesson 040 —— 面向对象简介

2019-02-11 13:01:49  阅读:231  来源: 互联网

标签:d2 面向对象 year print lesson d1 Data id 040


lesson 040 —— 面向对象简介

关于面向对象的简单介绍。

三大编程范式

  1. 面向过程编程
  2. 函数式编程
  3. 面向对象编程

面向对象概念

  • 类: 把一类事物相同的特征和动作整合到一起就是类。类是一个抽象的概念。类是一种数据结构。
  • 对象:就是基于类而创建的一个具体的事物(具体存在的),也是特征和动作整合到一起;对象就是类的实例化,具体化。对象是一个具体的事物。
  • 类与对象的关系: 对象是由类产生的,对象是类的实例化,具体化。
  • 实例化: 由类产生对象的过程叫实例化,类实例化的结果就是一个对象,或者叫一个实例(实例=对象)。
1. 声明类
class 类名:
    """类的文档字符串"""
    类体
    
# 声明一个类,类名一般首字母大写,使用驼峰命名法
# 代表的是:class Data(object):
class Data:
    """这是一个时间的类。"""
    pass

# 实例化这个类
d1 = Data()

在 Python3 中使用新式类,所有的类都继承自一个父类:object。

2. 属性

类是用来描述一类事物的,类的对象指的是一类事物中的一个个体。事物的属性分为:

  1. 数据属性: 就是变量
  2. 函数(方法)属性: 就是函数,在面向对象里称为方法。

注意:类和对象都使用点 . 来访问自己的属性。

3. 类的属性
  1. 类的数据属性: 类的数据属性是所有对象共享的

  2. 类的方法属性: 类的函数属性是绑定给对象用的

  3. 一些内置的类的特殊属性

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

    使用 dir(类名) 可以查看类的属性!!!

class Data:
    """关于时间的类"""
    
    # 类的数据属性
    year = 2018
    month = 7
    day = 35
    week = '星期三'
    
    # 类的方法属性
    def print_year():
        print('2018 年')
    # 需要传入参数和这个类绑定,不传也没问题,可是不会绑定
    # 可是要使用参数的时候,就需要传入 self
    def print_data(self):
        print('%4d 年 %2d 月 %2d 日' % (self.year, self.month, self.day))

if __name__ == '__main__':
    d1 = Data()
    d2 = Data()

    print("类的属性")
    print("Data.year: %d" % Data.year)
    print("Data.print_year: ")
    Data.print_year()
    # 这里类调用的话,就需要传入一个参数
    print("Data.print_data: ")
    Data.print_data(Data)
    print()
    
    print("类的属性是所有对象公有的")
    print("id Data.year: %d" % id(Data.year))
    print("id d1.year: %d" % id(d1.year))
    print("id d2.year: %d" % id(d2.year))
    print()
    
    print("函数属性是对于不同对象的")
    print("addr Data.print_data: ", Data.print_data)
    print("addr d1.print_data: ", d1.print_data)
    print("addr d2.print_data: ", d2.print_data)
    print("id Data.print_data: %d" % id(Data.print_data))
    print("id d1.print_data: %d" % id(d1.print_data))
    print("id d2.print_data: %d" % id(d2.print_data))
    print()

    print("d1 对象与类属性关系")
    print("d1.year: %d" % d1.year)
    # 这里不能调用,因为类里面是没有参数的,对象调用的话就会传入对象,即 self 参数
    #print("d1.print_year: ")
    #d1.print_year()
    print("d1.print_data: ")
    d1.print_data()
    print()

    print("类改变数据属性:")
    print("Data.year: %d" % Data.year)
    print("d1.year: %d" % d1.year)
    print("d2.year: %d" % d2.year)
    print("执行 Data.year = Data.year + 1")
    Data.year = Data.year + 1
    print("Data.year: %d" % Data.year)
    print("d1.year: %d" % d1.year)
    print("d2.year: %d" % d2.year)
    print()

    print("对象改变数据属性:")
    print("Data.year: %d" % Data.year)
    print("d1.year: %d" % d1.year)
    print("d2.year: %d" % d2.year)
    print("执行 d1.year = d1.year + 1")
    d1.year = d1.year + 1
    print("Data.year: %d" % Data.year)
    print("d1.year: %d" % d1.year)
    print("d2.year: %d" % d2.year)
    print("执行 d2.year = d2.year + 1")
    d2.year = d2.year + 1
    print("Data.year: %d" % Data.year)
    print("d1.year: %d" % d1.year)
    print("d2.year: %d" % d2.year)
    print()

    print("改变之后的地址")
    print("id Data.year: %d" % id(Data.year))
    print("id d1.year: %d" % id(d1.year))
    print("id d2.year: %d" % id(d2.year))
    print()

结果:

类的属性
Data.year: 2018
Data.print_year: 
2018 年
Data.print_data: 
2018 年  7 月 35 日

类的属性是所有对象公有的
id Data.year: 139849464558928
id d1.year: 139849464558928
id d2.year: 139849464558928

函数属性是对于不同对象的
addr Data.print_data:  <function Data.print_data at 0x7f313da13d90>
addr d1.print_data:  <bound method Data.print_data of <__main__.Data object at 0x7f313da440f0>>
addr d2.print_data:  <bound method Data.print_data of <__main__.Data object at 0x7f313da44128>>
id Data.print_data: 139849464102288
id d1.print_data: 139849465338376
id d2.print_data: 139849465338376
    
d1 对象与类属性关系
d1.year: 2018
d1.print_data: 
2018 年  7 月 35 日

类改变数据属性:
Data.year: 2018
d1.year: 2018
d2.year: 2018
执行 Data.year = Data.year + 1
Data.year: 2019
d1.year: 2019
d2.year: 2019

对象改变数据属性:
Data.year: 2019
d1.year: 2019
d2.year: 2019
执行 d1.year = d1.year + 1
Data.year: 2019
d1.year: 2020
d2.year: 2019
执行 d2.year = d2.year + 1
Data.year: 2019
d1.year: 2020
d2.year: 2020

改变之后的地址
id Data.year: 139849465104656
id d1.year: 139849464558832
id d2.year: 139849464558896

从以上实例中我们可以验证得到这几个结论:

  1. 类的数据属性是所有对象共享的,我们称为类的数据

    id Data.year: 139849464558928
    id d1.year: 139849464558928
    id d2.year: 139849464558928
  2. 当使用改变类的数据之后,我们发现,所有的对象数据都改变了,即他们的地址都是一样的。

    类改变数据属性:
    Data.year: 2018
    d1.year: 2018
    d2.year: 2018
    执行 Data.year = Data.year + 1
    Data.year: 2019
    d1.year: 2019
    d2.year: 2019
  3. 但是,我们使用对象改变类的属性之后,仅仅是这个对象的数据变了,而其它对象和类的都不会改变。我们可以得知:Python 中,直接改变对象中类的数据,其实是创建了新的对象数据,而不是改变了类的数据,即将指向类的数据的变量指向了一个新的数据地址!!!

    对象改变数据属性:
    Data.year: 2019
    d1.year: 2019
    d2.year: 2019
    执行 d1.year = d1.year + 1
    Data.year: 2019
    d1.year: 2020
    d2.year: 2019
    执行 d2.year = d2.year + 1
    Data.year: 2019
    d1.year: 2020
    d2.year: 2020
    
    id Data.year: 139849465104656
    id d1.year: 139849464558832
    id d2.year: 139849464558896

    注意:Python 中几乎所有变量的赋值,都是将新的数据地址赋值给这个变量,即这个变量指向了一个新的内存地址,而不是改变变量指向的对应内存地址的数据!!!

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

  5. 类中的函数属性需要一个 self 形参来和这个类的对象绑定。在 Python 中,self 代表的就是对象,定义的函数属性本质上是定义一个函数。(虽然不加 self 程序不会报错,但是不会和对象绑定)。虽然绑定了,但是当类调用的时候可以随便传入参数,只要传入的参数使函数可以运行。

    def print_data(self):
        print('%4d 年 %2d 月 %2d 日' % (self.year, self.month, self.day))
    
    Data.print_data(Data)
  6. 类的函数属性没有 self 参数的时候,只有类可以调用,对象是无法调用的,它是类的方法

    # 这里不能调用,因为类里面是没有参数的,对象调用的话就会传入对象,即 self 参数
    #print("d1.print_year: ")
    #d1.print_year()
  7. 通过类来创建对象的时候,对于绑定的类的函数,即有 self 形参的函数,实际上是将那个函数复制到了对象的空间中,有了自己的内存,与类中的地址不一样。所以,通过类创建对象,虽然是同一个类,同一个类的函数,但是,每个对象都会复制函数,每个对象有他们自己的存储这个函数的内存,即变成了对象自己的函数,而不是类的函数。虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法!!!

    addr Data.print_data:  <function Data.print_data at 0x7f313da13d90>
    addr d1.print_data:  <bound method Data.print_data of <__main__.Data object at 0x7f313da440f0>>
    addr d2.print_data:  <bound method Data.print_data of <__main__.Data object at 0x7f313da44128>>
    id Data.print_data: 139849464102288
    id d1.print_data: 139849465338376
    id d2.print_data: 139849465338376
  8. 强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将本身当做第一个参数传给方法,即自动传值(方法 __init__ 也是一样的道理)

    注意:绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数 selfself 可以是任意名字,但是约定俗成地写出self。

    # 类调用
    Data.print_data(Data)
    
    # 对象调用
    d1.print_data()
4. 对象

对象是类的实例化,类实例化的一个结果称为一个实例或者一个对象。

class Student:
    school='xxoo'
    def __init__(self, name, sex, age):
        print('开始创建')
        self.name = name
        self.age = age
        self.sex = sex
        print('创建结束')
    def learn(self):
        print('%s is learning' % self.name) #新增self.name

    def eat(self):
        print('%s is eating' % self.name)

    def sleep(self):
        print('%s is sleeping' % self.name)

# 创建对象
s1=Student('李坦克','男',18)
s2=Student('王大炮','女',38)
s3=Student('牛榴弹','男',78)

对象不仅有函数属性,还有类的数据属性,另外,还有它自己的数据属性。它们都可以通过 . 来访问

对象的 __dict__ 属性只有函数属性,说明了对象只有数据属性

要使用 __init__ 来设置初始化一个对象的方法,它没有返回值。

对于每一个类里定义的参数,都必须要有 self 形参,且必须要有,还要放在第一个位置。

5. 类属性增删改查

类属性的操作使用 .del 进行操作,当使用类进行类属性的更改,它的所有的实例对象,不管是改变之前创建的,或者是改变之后创建的,都会跟着改变;当使用对象对类属性重新赋值之后,类属性实际不会改变,而这个对象的类属性转变为对象属性。数据属性与函数属性都一样,同样的方式。

注意: 要调用类的属性,只能通过类名加点或者对象加点的方式调用,如果直接使用变量名,则调用的是全局的变量。调用不到类的属性。

country = '中国'
class N:
    country = '日本'
    num = ['a', 'b',]
    
    def __init__(self):
        print(country)   # 输出的是中国
    
n1 = N()
print(N.num)
print(n1.num)
n1.num.append(1)   # 没有给类属性赋新值,只是改变了类属性,所以结果是类属性改变了
print(N.num)
print(n1.num)

结果:

中国
['a', 'b']
['a', 'b']
['a', 'b', 1]
['a', 'b', 1]

标签:d2,面向对象,year,print,lesson,d1,Data,id,040
来源: https://www.cnblogs.com/arelive/p/python-40.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有