首页 > 其他分享 >day10

day10

时间:2023-08-01 16:12:22浏览次数:29  
标签:__ stu1 self course day10 print OldboyStudent

面向对象程序设计

  • 1940年以前:面向机器——二进制码、汇编
  • 面向过程——COBOL、FORTRAN、BASIC、C 语言等
  • 结构化程序设计——抛弃 goto 语句,采取“自顶向下、逐步细化、模块化”的指导思想。结构 化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块化”的方法,将软 件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。
  • 面向对象程序设计——C++、Java、C#等

杰出人物

  • 约翰·巴科斯,发明了Fortran。
  • 阿兰·库珀,开发了Visual Basic。
  • 艾兹格·迪杰斯特拉,开创了正确运用编程语言(proper programming)的框架。
  • 詹姆斯·高斯林,开发了Oak,该语言为Java的先驱。
  • 安德斯·海尔斯伯格,开发了Turbo Pascal、Delphi,以及C#。
  • 葛丽丝·霍普,开发了Flow-Matic,该语言对COBOL造成了影响。
  • 肯尼斯·艾佛森,开发了APL,并与Roger Hui合作开发了J。
  • 比尔·乔伊,发明了vi,BSD Unix的前期作者,以及SunOS的发起人,该操作系统后来改名为Solaris。
  • 艾伦·凯,开创了面向对象编程语言,以及Smalltalk的发起人。
  • Brian Kernighan,与丹尼斯·里奇合著第一本C程序设计语言的书籍,同时也是AWK与AMPL程序设计语言的共同作者。
  • 约翰·麦卡锡,发明了LISP。
  • 约翰·冯·诺伊曼,操作系统概念的发起者。
  • 丹尼斯·里奇,发明了C。
  • 比雅尼·斯特劳斯特鲁普,开发了C++。
  • 肯·汤普逊,发明了Unix。
  • 尼克劳斯·维尔特,发明了Pascal与Modula。
  • 拉里·沃尔,创造了Perl与Perl 6。
  • 吉多·范罗苏姆,创造了Python。

面向过程编程

面向过程变成的核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么然后干什么……

基于面向过程编程的思想编写程序好比在设计一条流水线,是一种机械式的思维方式。

  • 优点:复杂的问题流程化、进而简单化
  • 缺点:扩展性差

基于面向对象编程的思想编写程序,就好比是在创造一个世界,你就是这个世界的上帝,是一种上帝式的思维方式。

  • 优点:可扩展性强
  • 缺点:编程的复杂度要高于面向过程

类和对象

类的意思:种类、分类、类别

对象是特征与技能的结合体,我可能有身高体重、而你也有身高体重,所以你会说你像我,但是你一定不会说你像阿猫阿狗。并且我和你其实就可以说成是一类,而你和选课系统不能说是一类,因此给出类的定义:类就是一系列对象相似的特征与技能的结合体。

在现实世界中:先有一个个具体存在的对象,然后随着人类文明的发展才了分类的概念,既然现实世界中有类这个概念,Python程序中也一定有类这个概念,但是在Python程序中:必须先定义类,然后调用类来产生对象。

现实世界中定义类和对象

定义对象

就拿未来我们的选课系统来讲,我们先总结一套现实世界中的学生对象:

  • 对象1:

特征:

学校='oldboy'
姓名='耗哥'
年龄=18
性别='male'

技能:

选课

  • 对象2:

特征:

学校='oldboy'
姓名='猪哥'
年龄=17
性别='male'

技能:

选课

  • 对象3:

特征:

学校='oldboy'
姓名='帅翔'
年龄=19
性别='female'

技能:

选课

定义类

站在未来选课系统的角度,我们还可以总结现实世界中的学生类:

  • 老男孩学生类:

相似的特征:

学校='oldboy'

相似的技能

选课

程序中定义类和对象

定义类

class OldboyStudent():
    school = 'oldboy'
    
    def choose_course(self):
        print('is choosing course')
print(OldboyStudent.__dict__)
{'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x0000020B07BFE7B8>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}
print(OldboyStudent.__dict__['school'])
oldboy
print(OldboyStudent.__dict__['choose_course'])
<function OldboyStudent.choose_course at 0x0000020B07BFE7B8>
try:
    OldboyStudent.__dict__['choose_course']()
except Exception as e:
    print('error:',e)
error: choose_course() missing 1 required positional argument: 'self'

通过OldboyStudent.dict['choose_course']尝试访问OldboyStudent类中名为choose_course的属性,但是由于该属性不存在,所以会引发KeyError异常。

异常被捕获,并执行except代码块中的逻辑。

在except代码块中,使用print('error:', e)输出异常的消息。这里的e是KeyError异常对象,print函数会输出异常的消息,显示为error: 'choose_course',其中'choose_course'是引发异常的键名。

print(OldboyStudent.school)
oldboy
OldboyStudent.choose_course(111)
is choosing course
print(OldboyStudent.choose_course)
<function OldboyStudent.choose_course at 0x0000020B07BFE7B8>

打印OldboyStudent类的choose_course属性。但是由于类中没有名为choose_course的属性,所以引发了AttributeError异常。最终,我们捕获了异常并打印出错误消息。错误消息表明'OldboyStudent'对象没有choose_course属性。

OldboyStudent.__dict__['choose_course']
<function __main__.OldboyStudent.choose_course(self)>
OldboyStudent.country='China'
OldboyStudent.__dict__['country']
'China'
OldboyStudent.country='CHINA'
OldboyStudent.__dict__['country']
'CHINA'
del OldboyStudent.school
print(OldboyStudent.__dict__)
{'__module__': '__main__', 'choose_course': <function OldboyStudent.choose_course at 0x0000020B07BFE7B8>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None, 'country': 'CHINA'}

定义对象

调用类即可产生对象,调用类的过程,又称为类的实例化,实例化的结果称为类的对象/实例

class OldboyStudent():
    school = 'oldboy'
    def choose_course(self):
        print('is choosing course')
stu1=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
print(stu1.school)
oldboy
stu2=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
print(stu2.school)
oldboy
stu3=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
stu3.choose_course()
is choosing course

定制对象独有特征

class OldboyStudent:
    school = 'oldboy'
    
    def choose_course(self):
        print('is choosing course')
        
stu1 = OldboyStudent()
stu2 = OldboyStudent()
stu3 = OldboyStudent()
OldboyStudent.school = 'OLDBOY'
print(stu1.school)
OLDBOY
print(stu2.school)
OLDBOY

具体定制对象独有特征

  • 对象本质类似于类,也是一个名称空间,但是对象的名称空间存放对象独有的名字,而类中存放的是对象们共有的名字。因此我们可以直接为对象单独定制名字。
stu1.name = 'tank'
stu1.age = 18
stu1.gender = 'male'

print(stu1.name,stu1.age,stu1.gender)
tank 18 male
try:
    print(stu2.name,stu2.age,stu2.gender)
except Exception as e:
    print(e)
'OldboyStudent' object has no attribute 'name'
stu2.name = 'sean'
stu2.age = 19
stu2.gender = 'female'

print(stu2.name, stu2.age, stu2.gender)
sean 19 female

属性查找

首先从自身查找,没找到往类中找,类中没有则会报错。即对象的属性查找顺序为:自身--》类--》报错

类定义阶段定制属性

def init(obj,x,y,z):
    obj.name = x
    obj.age = y
    obj.gender = z
    
init(stu1,'tank1',181,'male1')
print(stu1.name,stu1.age,stu1.gender)
tank1 181 male1
init(stu2,'sean1',191,'female1')
print(stu2.name,stu2.age,stu2.gender)
sean1 191 female1
  • 使用上述方法虽然让我们定制属性更简单,但是还是太麻烦了,如果可以在实例化对象的时候自动触发定时属性,那就更方便了,因此可以使用类的__init__方法。
class OldboyStudent:
    school = 'oldboy'

    def __init__(self, name, age, gender):
        """调用类的时候自动触发"""
        self.name = name
        self.age = age
        self.gender = gender
        print('*' * 50)

    def choose_course(self):
        print('is choosing course')


try:
    stu1 = OldboyStudent()
except Exception as e:
    print(e)
__init__() missing 3 required positional arguments: 'name', 'age', and 'gender'
stu1 = OldboyStudent('nick', 18, 'male')
**************************************************
print(stu1.__dict__)
{'name': 'nick', 'age': 18, 'gender': 'male'}

对象属性查找顺序

属性查找

先从对象自己的名称空间找,没有则去类中找,如果类也没有则报错

class OldboyStudent:
    school = 'oldboy'
    count = 0
    aa = 10

    def __init__(self, x, y, z):  #会在调用类时自动触发
        self.name = x  # stu1.name='耗哥'
        self.age = y  # stu1.age=18
        self.sex = z  # stu1.sex='male'
        OldboyStudent.count += 1
        #         self.count += 5
        self.aa = 1

    def choose_course(self):
        print('is choosing course')
print(OldboyStudent.count)
0

类属性 school:这是一个类级别的属性,被所有 OldboyStudent 类的实例对象共享。在这个例子中,school 被赋值为字符串 'oldboy'。

类属性 count:这是另一个类级别的属性,用于记录 OldboyStudent 类的实例对象的数量。初始值为 0。

类属性 aa:这是另一个类级别的属性,被所有 OldboyStudent 类的实例对象共享。在这个例子中,aa 被赋值为 10。

init 方法:这是一个特殊方法,在创建 OldboyStudent 类的实例对象时会自动调用。它接受 x、y 和 z 作为参数,并将它们分别赋值给实例对象的属性 self.name、self.age 和 self.sex。在这个例子中,init 方法还对类属性 count 进行了递增操作 OldboyStudent.count += 1,表示创建了一个新的对象。另外,它还为实例对象的属性 self.aa 赋值为 1。

choose_course 方法:这是一个普通的实例方法,用于表示学生正在选择课程。

在这个类中,school 和 count 是类级别的属性,可以通过类名来访问,例如 OldboyStudent.school 和 OldboyStudent.count。而 name、 age、 sex 和 aa 是实例级别的属性,需要通过对象来访问,例如 stu1.name、 stu1.age、 stu1.sex 和 stu1.aa。

注意,在 init 方法中,你可以使用 self.name、 self.age、 self.sex 和 self.aa 来引用实例对象的属性,而使用 OldboyStudent.count 或 OldboyStudent.aa 来引用类属性。

该类定义了一个简单的构造方法和一个方法,可以创建 OldboyStudent 类的实例对象,并通过实例对象来访问和修改实例属性。

请注意,当你创建 OldboyStudent 类的实例对象时,init 方法将会被自动调用,并且传入的参数值将被用来初始化实例对象的属性。

stu1 = OldboyStudent('nick', 18, 'male')
print(stu1.count)
1
stu2 = OldboyStudent('sean', 17, 'male')
print(stu2.count)
2
stu3 = OldboyStudent('tank', 19, 'female')
print(stu3.count)
3
print(OldboyStudent.count)
3
print(stu1.name)
nick
  • 由于上述修改的是类属性,类属性的count已经被修改为3,所以其他实例的count都为3
print(stu1.count)
3
print(stu2.count)
3
print(stu3.count)
3
  • 由于aa是私有属性,因此stu们都会用自己私有的aa,不会用类的aa
print(stu1.__dict__)
{'name': 'nick', 'age': 18, 'sex': 'male', 'aa': 1}
print(stu2.__dict__)
{'name': 'sean', 'age': 17, 'sex': 'male', 'aa': 1}
print(stu3.__dict__)
{'name': 'tank', 'age': 19, 'sex': 'female', 'aa': 1}

对象的绑定方法

对象的绑定方法

class OldboyStudent:
    school = 'oldboy'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.sex = gender

    def choose_course(self):
        print(f'{self.name} choosing course')

    def func(self):
        print('from func')
  • 类名称空间中定义的数据属性和函数属性都是共享给所有对象用的
  • 对象名称空间中定义的只有数据属性,而且是对象所独有的数据属性

类使用对象的绑定对象

stu1 = OldboyStudent('nick', 18, 'male')
stu2 = OldboyStudent('sean', 17, 'male')
stu3 = OldboyStudent('tank', 19, 'female')

print(stu1.name)
print(stu1.school)
nick
oldboy
  • 类中定义的函数是类的函数属性,类可以使用,但使用的就是一个普通的函数而已,意味着需要完全遵循函数的参数规则,该传几个值就传几个
print(OldboyStudent.choose_course)

<function OldboyStudent.choose_course at 0x000002DEDCA832F0>
try:
    OldboyStudent.choose_course(123)
except Exception as e:
    print(e)
is choosing course

对象使用对象的绑定方法

  • 类中定义的函数是共享给所有对象的,对象也可以使用,而且是绑定给对象用的,

  • 绑定的效果:绑定给谁,就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入

print(id(stu1.choose_course))
print(id(stu2.choose_course))
print(id(stu3.choose_course))
print(id(OldboyStudent.choose_course))
3156207784456
3156207762440
3156207784456
3156208005872
print(id(stu1.school))
print(id(stu2.school))
print(id(stu3.school))
3156207789592
3156207789592
3156207789592
print(id(stu1.name), id(stu2.name), id(stu3.name))
3156208430920 3156208429296 3156208431032
stu1.choose_course()
nick choosing course
stu2.choose_course()
sean choosing course
stu3.choose_course()
tank choosing course
  • 补充:类中定义的函数,类确实可以使用,但其实类定义的函数大多情况下都是绑定给对象用的,所以在类中定义的函数都应该自带一个参数self
stu1.func()
from func
stu2.func()
from func

类和数据类型

类与数据类型

python3中统一了类与类型的概念,类就是类型

class Foo:
    pass

obj = Foo()
print(type(obj))
<class '__main__.Foo'>
lis = [1,2,3]
lis2 = [4,5,6]
print(type(lis))
<class 'list'>

lis和lis2都是实例化的对象,因此lis使用append方法和lis2无关

lis.append(7)
print(lis)
[1, 2, 3, 7]
print(lis2)
[4, 5, 6]

list.append()方法原理

class OldboyStudent:
    school = 'oldboy'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.sex = gender

    def choose_course(self, name):
        print(f'{name} choosing course')


stu1 = OldboyStudent('nick', 18, 'male')
stu1.choose_course(1)  # OldboyStudent.choose_course(stu1, 1)
1 choosing course
OldboyStudent.choose_course(stu1, 1)
1 choosing course
lis = [1, 2, 3]  # lis = list([1,2,3])
print(type(lis))
<class 'list'>
lis.append(4)  # list.append(lis,4)
print(lis)
[1, 2, 3, 4]
list.append(lis, 5)
print(lis)
[1, 2, 3, 4, 5]

对象的高度整合

没有对象

以未来我们要连接数据库举例,如果没有面向对象的思想,我们只要想要使用一个方法,就必须得这样做

import pymysql  # 连接mysql的三方库,可以pip3 install pymysql安装


def exc1(host, port, db, charset, sql):
    conn = pymysql.connect(host, port, db, charset)
    conn.execute(sql)
    return xxx


def exc2(proc_name):
    conn = pymysql.connect(host, port, db, charsett)
    conn.call_proc(sql)
    return xxx


exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t1')
exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t2')
exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t3')
exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t4')
  • 由于host、port、db、charset可能是固定不变的,sql一直在变化,因此我们通过上述的方法实现不同的sql语句,非常麻烦,因此我们可以改用默认形参
def exc1(sql, host='1.1.1.1', port=3306, db='db1', charset='utf-8'):
    conn = pymysql.connect(host, port, db, charset)
    conn.execute(sql)
    return xxx

exc1('select * from t1')
exc1('select * from t2')
exc1('select * from t3')
exc1('select * from t4')
  • 虽然是用默认参数简化了操作,但是对于不同引用的对象,参数并不是一成不变的,或者我们需要对exc2方法进行修改,这是非常麻烦的,因此可以考虑使用面向对象

有对象

  • 有了面向对象之后,对于上述的例子,我们可以这样做
import pymysql


class Foo:
    def __init__(self, host, port, db, chartset):
        self.host = host
        self.port = port
        self.db = db
        self.charset = chartset

    def exc1(self, sql):
        conn = pymysql.connect(self.host, self.port, self.db, self.charset)
        conn.execute(sql)
        return xxx

    def exc2(self, proc_name):
        conn = pymysql.connect(self.host, self.port, self.db, self.charsett)
        conn.call_proc(sql)
        return xxx


obj1 = Foo('1.1.1.1', 3306, 'db1', 'utf-8')
obj1.exc1('select * from t1')
obj1.exc1('select * from t2')
obj1.exc1('select * from t3')
obj1.exc1('select * from t4')

obj2 = Foo('1.1.1.2', 3306, 'db1', 'utf-8')
obj2.exc1('select * from t4')
  • 对于上述发生的现象,我们可以总结对象其实就是一个高度整合的产物,整合数据与专门操作该数据的方法(绑定方法)

标签:__,stu1,self,course,day10,print,OldboyStudent
From: https://www.cnblogs.com/qingchuan/p/17596797.html

相关文章

  • day10 10.1 C语言基础之编译器安装
    【一】学习C语言的原因一般公司的apk基于Java实现的加密jadx反编译java,分析代码NB公司的的apk,基于Java+C语言实现加密(JNI开发)加密一般使用C语言开发,在安卓项目中使用Java调用C语言开发的动态链接库文件jadx反编译java,分析代码看不到加密ida反编译c语言,分析代码......
  • day10 栈与队列
    232.用栈实现队列题解:这一题在大学的时候学过,用两个栈来实现队列,队列是先进先出,而栈是先进后出,所以需要两个栈一个用来存队列入队的数据,出队列的时候,需要将顺序调转,这时候就需要用到另一个队列,注意好边界条件就行225.用队列实现栈题解:队列实现栈的功能也不难,主要是想到栈......
  • day10
    OtterCTF2018一、[OtterCTF2018]Whatthepassword?1.使用volatility2获取内存镜像的版本信息python2vol.py-f'/home/cpyq/Desktop/OtterCTF.vmem'imageinfo2.使用mimikatz直接获得密码和用户信息python2vol.py-f'/home/cpyq/Desktop/OtterCTF.vmem'--profile=Wi......
  • vue-day10--键盘事件
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width,initial-scale=1.0"/><title>Document</title><script......
  • Day10-设计模式之外观模式
    设计模式之外观模式一、引例当我们现在想要在家通过投影仪看电影,其过程包括关灯,关闭窗帘,打开投影仪,这些家居都是独立的,就会有灯光开关、窗帘开关、投影仪开关。我们需要一步一步的去打开这些开关。如果用代码来实现,就可将灯光,窗帘等都看成一个对象,然后用Client端依次去调用这些......
  • 算法练习-day10
    栈和队列20.有效的括号题意:给定一个只包括'(',')','{','}','[',']' 的字符串s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号示例:    思路:本题我有两种思路,1.双栈存储:我们可......
  • 尚医通-day10【微信扫码登录】(内附源码)
    第01章-准备工作1、申请微信登录https://open.weixin.qq.com(1)注册开发者账号:准备营业执照(2)邮箱激活(3)完善开发者资料(4)开发者资质认证:1-2个工作日审批、300元(5)创建网站应用:提交审核,7个工作日审批(免费)(6)熟悉微信登录流程参考文档:https://developers.weixin.qq.com/doc/oplat......
  • 闲话 Day10
    已经是第10期了。总体来说还是很高产的吧(?)然而,写闲话是需要大量思考的吧。而最近比较困,所以啥也没想,或者说至少除了学术以外啥也没想。然后才想起来,我要写的是闲话,不是什么大众读物。不需要有什么主题,不需要有大致内容或者方向。就随便写一写漫天乱逛可能更像是一篇闲话吧......
  • day10-Spring Cloud Alibaba Nacos-服务注册与配置中心
    SpringCloudAlibabaNacos-服务注册与配置中心官网:https://github.com/alibaba/nacos,Nacos官方中文手册Nacos:SpringCloudAlibaba服务注册与配置中心(非常详细)(biancheng.net)SpringCloudAlibaba系列-一文读懂Nacos原理-掘金(juejin.cn)1.什么是NacosNacos/nɑ:k......
  • day109-smbms准备工作
    smbms项目部署环境创建项目<?xmlversion="1.0"encoding="UTF-8"?>​<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://mave......