面向对象编程【Python】

一、编程语言的发展:

机器语言 —> 汇编语言 —> 高级语言(面向过程的 C ) —> 面向对象(c++、Java、Python) 越高级,程序员就可以越偷懒

要把大象塞冰箱总共分几步?

二、面向过程:

1.先把冰箱打开;2.把大象塞进去;3.把冰箱关上
定义一个函数来实现功能:def {1.先把冰箱打开;2.把大象塞进去;3.把冰箱关上 }
往后遇到要实现把大象装冰箱这个操作时,直接调用函数就行

三、面向对象:

  • 群体:“妈妈” —— 抽象 —— 类
  • 个体:“李妈妈” —— 具体 —— 对象

对象: 所有你能看到的东西都是对象。对象是具有 属性 和 方法 的实物,(桌子、水杯、电灯、墙…都是对象),

  • 属性:
    是静态的名词性的描述一个东西,比如说:电扇这个对象的属性有 高度、重量、颜色、风力大小、额定电压 等。

  • 方法:
    是指对象的功能和行为,风扇的功能能就是吹风。

四、类:具有相同 “属性” 和 “方法” 的抽象

一个抽象的名词,没有特征,没有特指,模糊的东西,就叫 ,比如说:桌子,你不知道哪一个桌子,不知道什么样的桌子

类是对一系列事物的统称,同类事物必定具有相同的特征

特征分类:

  • 状态(静态化) —— 变量 / 属性(成员变量)
  • 行为(动态化) —— 方法(成员方法)
    统称:类的成员

类的定义:

 # 定义格式一:
class 类名:
    pass
    
 # 定义格式二:
class 类名:
    成员变量 >>> 静态化的状态 年纪 国籍 身高 体重
    成员方法 >>> 动态化的行为 函数

1、成员变量:

	# 定义格式一:
class 类名:
   “”“成员变量 >>> 静态化的状态 ”“”
  def __init__(self): # 定义成员的变量 固定的语法格式
     self.变量名1 =1  # 成员变量
     self.变量名2 = None  # 并不确定该属性具体的值

>>> 成员方法 —— 动态化的行为 函数
     
	# 调用格式:
取值:对象名.变量名
赋值:对象名.变量名 =# 创建对象
变量名 = 类名() # 对象名
print(变量名.方法)
	# 定义格式二:
对象名.变量名 =# 创建对象出来之后,属于该对象独有的属性/变量

	# 调用格式
取值:对象名.变量名
赋值:对象名.变量名 =

2、成员方法:

	# 定义格式一:
class 类名:
   def 方法名(self):
       方法体
	
	# 调用格式
对象名.方法名()

self 仅在声明时占位,无需传递具体参数

	# 定义格式二:
class 类名:
	def 方法名(self,形参1,形参2,......):
 		方法体
 		
	# 调用格式一:
  	对象名.方法名(实参1,实参2,......)

怎么表示类呢

class person():  # 类
    def __init__(self, name, age, sex, heigh):  # 属性写括号里
        self.name = name  # self 的含义代表即将要出现的面向对象
        self.age = age
        self.sex = sex
        self.heigh = heigh

    def say(self):
        print(self.name, self.age, self.sex, self.heigh, "hello")


p = person("name", 18, "男",180)  # 运行 __init__ 方法
p.say()

(1)属性(这个类的一些名词属性):

在这里插入图片描述

上面定义了属性(name、age、sex、height),又定义了方法say(),这样就构成了一个类,但是类是一个抽象的概念,你想让“人说话”,就得把抽象的类实例化具体哪个人说话,那么下面的p就是一个对象,p = person(),但是就这样一个模糊的人,你不知道它具体长啥样,于是需要在括号里填属性:p = person(“name”,18, “男”, 180),这样创建一个人就能具体实实在在知道他是谁,然后就可以运行功能p.say(),我想让他做自我介绍,然后就是在say() 方法里面设置属性:

def say()
print(self.name, self.age, self.sex, self.height, "hello")

所以,创建对象之前,得要有一个类,一个概念性的东西,抽象的类就是一个造汽车的图纸,只有根据图纸造出具体的对象汽车了,才可以使用汽车的一些方法

在这里插入图片描述

__init__    叫:构造函数,构造啥用的呢?构造 对象p 用的。

只要你写一个类名加一个括号,这个构造函数__init__是自动调用的,只要创建了对象,那么类里面的构造方法就会被自动调用,我们也把__init__叫做 魔法方法

然后构造函数下面出现一系列的 self属性,self 的含义代表即将要出现的那个对象p,self 指向的就是p,临时指向新创建的对象(等具体的新对象p来接手)

如下:如果你临时创建的对象没有东西指向它的话,系统会认为它是一个垃圾,所以需要self临时指向一下这一串内存地址,有了一个名字,这时候它就不是垃圾了在这里插入图片描述
但最后还得回到具体的新对象p去指向,因为当你再创建其它新对象了,self就又得去指向新的对象了

整体捋一遍:
在这里插入图片描述
在这里插入图片描述

问:构造函数里有没有return?

init 方法 可以有return,但return必须是 return None,其实返回None, 最终接收的还是 self 对象;
(理论上说应该返回self,这样才能把self的值赋值给P,这样说理论是对的,但是实际上一般在init方法里不写return)
或者说 没有 return,但是构造函数init方法会给返回一个值,返回一个 临时对象self 赋给 新创建的对象p

在这里插入图片描述

(2)方法 —— 这 个 类 所 具 有 的 功 能 :

静态方法:

在这里插入图片描述
如上图,
静态方法是不依赖对象的,通过类,就可以使用这个方法;

say()方法静态方法run() 的存储空间是不一样的,前者say()基于 对象,后者run()基于
所以 run( ) 通过 类 来调用, say( ) 通过 对象 来调用,静态方法 run( ) 也可以通过对象来调,但是得 传对象,

看一下两种方法的内存模型是怎么样的:
在这里插入图片描述
当然,静态方法也可以用对象来调用的:p.run()

如下:
下图 为 对象直接调用静态方法,调用时少了四个参数,
在这里插入图片描述
下图 为 传完对象后 的调用成功:
在这里插入图片描述
所以,
类方法 只能 类 来调用,
静态方法 是 类 和 对象 都可以调用

对象对象 通过类名 后加一个 括号 的形式 来创建,创建后 里面的一个内存模型,怎么赋值的要知道

str 魔术方法的介绍

class man:
    def __init__(self):
        self.gender = '男性'
        self.age = None

    # 成员方法 定义部分
    def sing(self,num1):
        print('唱了%s首歌' % num1)


    def dance(self,num2):
        print('跳了%s只舞' % num2)

    # def __str__(self):
        # return一个返回值
        # return '这个类是创建人类的末班'

man1 = man()
print(man1)

在这里插入图片描述

class man:
    def __init__(self):
        self.gender = '男性'
        self.age = None

    # 成员方法 定义部分
    def sing(self,num1):
        print('唱了%s首歌' % num1)


    def dance(self,num2):
        print('跳了%s只舞' % num2)

    def __str__(self):
        # return一个返回值
        return '这个类是创建人类的末班'

man1 = man()
print(man1)

在这里插入图片描述
str魔术方法,特定的时机去进行调用,在使用print函数打印对象的时候,会自动执行代码,也属于魔术方法

	# 定义格式:
 def __str__(self):
 	return '显示的信息'

五、面向对象的三大特性:

  • 继承
  • 封装
  • 多态

1、继承(涉及到好几个类的关系处理)

优点减少代码量,把一些重复的、共用的代码提出去,但并不是这个共同部分就归谁所有,只是调用共同代码的使用权,

缺点耦合程度太高(比如,下述继承案例中:cat 如果不和 animal 建立联系的话,那么 cat类 就什么用都没有,就是一个废类,那咱们写代码的时候,要尽可能的减低代码类与类之间的耦合程度------> 高内聚、低耦合

  • 构造函数:没有显示和声明时,系统会自动给

  • 子类使用父类属性时,必须手动调用父类构造函数

  • 重写和覆盖:当父类方法不能满足子类的需要时,则在每个子类中都要覆盖,

比如:
猫也要吃,狗也要吃,但猫吃猫粮,狗吃狗粮,它不一样;
如果吃的方法一样,可以继承父类,吃的方法不一样,那就只能覆盖了

# 这是源代码:

class cat():
   def __init__(self,name,weight,age):
      self.name = name
      self.age = age
      self.weight = weight

   def eat(self):
      print("吃饭")
   def run(self):
      print("跑步")
   def sleep(self):
      print("睡觉")

class dog():
   def __init__(self,name,weight,age):
      self.name = name
      self.age = age
      self.weight = weight

   def eat(self):
      print("吃饭")
   def run(self):
      print("跑步")
   def sleep(self):
      print("睡觉")

---------------------------------------------------

# 这是采用继承后的代码:

class animal():

   def __init__(self, name, weight, age):
      self.name = name
      self.age = age
      self.weight = weight

   def eat(self):    #下面的吃饭、跑步、睡觉,这三个方法是父类的方法,这些父类的方法想要调用得通过 animal父类 的对象来调用
     print("吃饭")

   def run(self):
     print("跑步")

   def sleep(self):
     print("睡觉")

class cat(animal):     # cat是子类,animal是父类    
# 构 造 函 数 在 没 有 写 上 显 示 声 明 时 ,系 统 会 默 认 提 供 ----> def __init__ (self):    
   pass
class dog(animal):
   pass

c = cat()
d = dog()
c.sleep()   # 子类对象进行调用父类方法
d.eat()

在这里插入图片描述

小实验:

验证 父类对象到底创没创建 ,如果创建了,那么 print(“这是父类构造函数”) 一定会走

只需要看看父类构造函数能不能运行出来,如果运行出来了,那说明它底层给咱们构造了一个函数,只是咱们没看见

结果,没有走父类

下图所示,父类构造函数没有运行出来,那是怎么调用父类的呢
在这里插入图片描述

怎么创建父类对象呢?

下面把属性打开:
在这里插入图片描述
子类使用父类属性时,必须手动调用父类构造函数
这种 手动调用的方法是绝对没有问题的,括号里写三个参数,属性
在这里插入图片描述
调用父类属性的时候,使用的是父类本身的属性,而不是父类属性的复印版(如下图 id 验证问题:调用的属性是父类本身)
在这里插入图片描述

重写和覆盖:

当父类方法不能满足子类的需要时,则在每个子类中都要覆盖,比如:猫也要吃,狗也要吃,但猫吃猫粮,狗吃狗粮,它不一样;如果吃的方法一样,可以继承父类,吃的方法不一样,那就只能覆盖了

class animal():
   def __init__(self, name, weight, age):
      self.name = name
      self.age = age
      self.weight = weight
      print(id(self.name))
   def eat(self):
      print("吃饭")
   def run(self):
      print("跑步")
   def sleep(self):
      print("睡觉")

class cat(animal):
   def __init__(self):
     super().__init__("小花",2,2) # super() 手动调用父类init方法
       print("这是子类构造函数")
   def eat(self):
       print("猫粮")
     pass

c = cat()
c.eat()

在这里插入图片描述

多继承的继承顺序是:

先找本身(子类)—> 再找继承的父类1(亲父类) —> 再找继承的父类2 —> 再找继承的父类3 (若父类没了!---->就找爷爷(父类的父类))===>要是找一圈都没有这个方法,就会报错了!

【二叉树:从左到右,一层一层找,这个叫:广度优先

class father0():
    def __init__(self):
       print("这是亲爹")
    def fun0(self):
       print("功能1:当大官")

class father1():
    def __init__(self):
       print("这是干爹1号")
    def fun1(self):
       print("功能2:变有钱")

class father2():
    def __init__(self):
       print("这是干爹2号")
    def fun2(self):
       print("功能3:找媳妇")

class son(father0,father1,father2):
     pass

s =son()
s.fun0()
s.fun1()
s.fun2()

在这里插入图片描述

六、字符串练习

1.字符串解析,现有一字符串,“卡巴斯基#杀毒软件#免费版#俄罗斯#”,解析出每个元素

str = "卡巴斯基#杀毒软件#免费版#俄罗斯#"
str = str[:-1]  # -1表示最后一个元素的下标 || 也可以用:str = str[:len(str)-1]
print(str.split("#")) #考察的方法是 split()

在这里插入图片描述
2.“那车水马龙的人世间,那样地来 那样地去,太匆忙”最后一次出现“那”的位置。

str = "那车水马龙的人世间,那样地来 那样地去,太匆忙"

index = str.rfind("那")

print(index)

在这里插入图片描述
3.判断输入的字符串是否是.py结束

str = input("请输入一个字符串:")
if str[-3:]==".py":
   print(True)
else:
   print(False)

在这里插入图片描述
在这里插入图片描述
4.有一个身份证号码,判断此为男还是女,基于此方法,写一个算法,判断一个身份证号为男还是女。(身份证号分15位和18位)

def is_man(idcard):   
    if len(idcard)==18:
       return True if int(idcard[-2])%2 !=0 else False  #身份证号倒数第二位奇数是男性,偶数位女性    
    if len(idcard)==15:
       return True if int(idcard[-1])%2 !=0 else False  #身份证号倒数第一位奇数是男性,偶数位女性

b = is_man("420984199802048416")
print(b)

在这里插入图片描述
18位身份证,看倒数第二位,为奇是男性
15位身份证,看倒数第一位,为奇是男性

5.有如下格式的字符串name-age-sex-address,解析出姓名,年龄等信息

str = "name-age-sex-address"
print(str.split("-"))

在这里插入图片描述
6.求出字符串中有多少种字符,以及每个字符的个数
static void printCharInfo(String str)
例如有字符串 str=“apple is a apple.”:
结果应该是:

(考察的点在排序,先转列表再排序)
字符串转列表:list = [str[i] for i in s]

s = "apple is a apple."
list = [str(i) for i in s]
list.sort()  # 排完序
print(list)

count = 0
a = list[0]

for item in list:
  if item==a:
     count+=1
  else:
     print(a,":",count)
     count = 1
    a = item
print(a,":",count)

在这里插入图片描述


七、总结:

1,面向过程 和 面向对象

class  类名():
    类的体(属性和方法)

2,创建对象

引用(变量) = 类名()
__init__(self)  构造函数

3,方法:类方法 对象方法
4,面向对象的三大特性:继承 封装 多态

class 子类/派生类(父类/超类/基类):
class A(object):
   def a():
       pass
   pass

class B():
   def b():
       pass
   pass

class C(B)    # C把B继承过来了,C也可以同时有自己的方法

class D(A,B,C):   # 多继承,D 把 A、B 、C都继承过来了
   def b():

从左到右,整体深度优先 局部广度优先(有菱形结构)
覆盖/重写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值