当前位置: 首页>移动开发>正文

入门python(第六篇)面向对象编程 & 类(Class)

(一)面向对象编程

看到这个名字我不知道你会不会有疑惑,编程就编程呗,咋还欺负单身狗呢?非得找个对象像吗?非也。在程序员的眼里,万物皆对象

那么对象是什么呢?简单地说,对象是一个具体存在的事物,占据时空位置。面向对象意思就是,python这门编程语言,的关注点是对象。它把所有东西都看作是对象。例如:一个标量是一个对象,一个变量是一个对象……。面向对象的 还有c++,Java等

与面向对象不同的是面向过程:这样的编程语言是更注重解决问题的过程。也就是解决问题的先后顺序。第一步,第二步……。其中C语言就是代表。

举个例子!一个古老的例子。
用两种思想解决:把大象装进冰箱里。

入门python(第六篇)面向对象编程 & 类(Class),第1张

感觉是不是极为不一样,我们用代码实现以下。而且要注意的是,面向对象和面向过程是一种思维,一种解决问题的编程思维。
  • 面向过程
# 面向过程
# 冰箱有四个格子
fridge  = [None,None,None,None]
elephant  = "elephant"
fridge[0] = elephant
print(fridge)  # ['elephant', None, None, None]
  • 面向对象(里面有部分代码是下面会讲到的)

# 创建冰箱类
class Fridge():
    def __init__(self) -> None:
        self.storage = [None,None,None,None] # 冰箱有四个内存
    # 实现放东西进去的函数
    def put(self,x):
        for i in range(len(self.storage)):
            if (i == len(self.storage)-1) and (self.storage[i] !=None):
                print("冰箱满咯")
                break

            if self.storage[i] == None:
                self.storage[i] = x
                break
        print(self.storage)
            

# 面向对象
fridge = Fridge() # 创建一个冰箱对象
elephant = "elephant" # 创建大象对象
fridge.put(elephant) # ['elephant', None, None, None]

最终的输出结果是一样的,可是两种思想极为不同。第一种符合逻辑思维,第二种更像是现实世界我们的做法。

第一种方法它的整体是紧密相连的,即高耦合,没有明确的分工。这在大型的项目中其实是不太好的,如果以后的代码要改,你得从上往下看代码,估计你得找半天。

第二种做法,也有一定的局限性,他需要首先将冰箱的所有属性和功能都定义好,如果没有这个方法,就没法实现。但是加功能也是方便的,有利于代码的维护。

这便是面向对象面向过程了。

(二)类 class

理解完上面那些,我们可得好好看一下面向对象具体的工作流程是怎么样的。也就是理解一下上面看不懂的代码是啥。

我们先说一下,面向对象的过程:创建类=>创建实例对象=>调用方法实现需求=>类和对象维护

(1)从上面的代码中我们看到了创建冰箱类,那么类是什么?

简单地讲,就是一类事物,例如:人类,鸟类,动物,植物,微生物。这些都不是具体的事物,所以类不是对象。上面说过对象是要具体的实物。

想必你大概知道是啥东西了吧?它是一类事物属性特征和功能的集合。

举个例子!

  • 人类:
    属性:名字,一个脑袋,四肢,有衣服,等
    功能:吃、喝、拉、撒、走、跑、蹦、爬……

那么怎么用代码操作呢?

# 定义人类
class person():
  # 属性特征
  name=""
  head = 1
  limb = 4
  clothes = True

  # 功能:
  def eat(self):
    print("i can eat!")

  def run(self):
    print("i can run!")

(2)如何创建一个实例对象呢?

我们知道了人类是个啥意思。那么李四和人类的关系呢?李四叫做对象,因为他是一个具体的人,它属于人类。在python里面,我们可以把李四叫做是人类的一个实例对象。一个特殊的人。

lisi = person() # 这个过程叫做实例化,把抽象的人转变为具体的人的过程。
lisi.name = "lisi"
(3)理解 => 实践

通过这样的解释,估计大家对类和实例对象都有了深刻的理解。如果还不够深刻,那就再看一遍。

类定义的代码格式:
类名一般是大写开头的。

class 类名(参数列表):
  # 属性和功能

类里面的变量:类变量和实例变量
类变量:不需要实例就可以直接使用,相当于绑定在类上,而不是绑定在实例上。但是,类变量也可以在实例中调用。所有类别实例之间可以共享的值。一般不使用。
实例变量:绑定在实例上,无法通过类访问得到

通过代码来理解类变量和实例变量的区别,访问变量和函数的方法:实例.变量、实例.方法()

class Person():
    # 这个是类变量
    head = 1

    # 注意这里的参数self,这是专门用来指向实例对象的,私人定制哦。
    # 而且类里面的方法(类里面的函数都叫做方法)的第一个参数必须是self
    # 使用这个函数来设置参数。
    def set_attr(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age

    # 类里面的函数叫做方法
    # 他和函数唯一的区别就是,必须要有参数,且第一个参数是self,原因是为了绑定实例对象的一些属性嘛
    def eat(self):
        print("i can eat!")

    def run(self):
        print("i can run!")

# 中文也能做变量名哦,但是绝对不要使用,这里只是个例子
张三 = Person() # 实例化

print(Person.head) # 1
print(张三.head) # 1
张三.head = 2
print(Person.head) # 1 注意,这里是不会改变的哈
print(张三.head) # 2

张三.set_attr("张三","男",18)
print(张三.name,张三.sex,张三.age) # 张三 男 18
print(Person.name) # AttributeError: type object 'Person' has no attribute 'name'

好了理解完,类变量和实例变量的区别之后,我发现一个小问题,我们写了一个函数来给实例赋值,调用set_attr我感觉还是太麻烦了。能不能在我实例化的时候就设置好了呢?

答案是python提供了这样的方法,叫做构造函数,我们有时候也叫初始化函数。

构造函数:在我们初始化实例的时候,它会自动调用构造函数,主要适用于帮我们完成一些变量和函数的初始化。这个函数的名字叫做 __init__()

于是上面的代码又可以写成这样:

class Person():
    # 构造函数
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age

    def eat(self):
        print("i can eat!")

    def run(self):
        print("i can run!")

# 注意了哦,这里面现在必须根据__init__函数里面的参数列表进行传参哦,否则会报错。
张三 = Person("zhangsan","man",19) # 实例化
print(张三.name,张三.sex,张三.age) # 张三 男 19

继承:也就是说,类可以继承一个类,被继承的类叫做父类,继承的类叫做子类。怎么理解呢?动物是一个类,人类是一个类,但是人类属于动物。

子类可以使用父类的方法,继承的方法就是在列表参数里加上父类的类名。

直接上代码!

class animal():
    def sleep(self):
        print("i am sleepy!")

# 继承
class Person(animal):
    # 这个是类变量
    head = 1

    # 构造函数
    def __init__(self,name):
        self.name = name

    def eat(self):
        print("i can eat!")

zhangsan = Person("zhangsan")
zhangsan.eat()
zhangsan.sleep()

多继承:可能一个事务并不只是一类,可能属于很多类。橘猫属于猫,属于猫科动物,属于动物,属于生物。

class creatures():
    a = 3
class animal():
    a = 1
class cat(animal,creatures):
    a = 2

c = cat()
print(c.a) # 2 就近原则,先在自己的作用域找,找不到,就根据参数列表按顺序找
class creatures():
    a = 3
class animal():
    a = 1
class cat(animal,creatures):
    b = 2

c = cat()
print(c.a) # 1 cat里面没有a,根据参数列表在animal里面找到了。

现在进入下一个话题:方法重写

啥意思嘞,就是说,有时候父类有一个方法,我觉得不满足我的需求,我想重新写过。这时候python给出了解决方案:方法重写。

补充一个小知识点:所有的类都默认继承自object。里面有一个str()方法用来打印实例对象的信息的。我们现在重写这个方法!

class animal():
    def __init__(self,name,sex) -> None:
        self.name = name
        self.sex = sex

a=animal("猫","母")
# 我们直接print(实例变量),python会自动调用__str__方法
print(a) # <__main__.animal object at 0x0000025A8460E5C0> 显示的内容看不懂,重写该方法 
class animal():
    def __init__(self,name,sex) -> None:
        self.name = name
        self.sex = sex
    
    def __str__(self) -> str:
        return "Animal, name:{},sex:{}".format(self.name,self.sex)

a=animal("猫","母")
print(a)

还有一个没说到的知识点就是supper(),supper()是一个类,简单来讲,它可以用于调用父类中的方法。这样的说法是不严谨的。
了解更多:
【1】https://blog.csdn.net/wanzew/article/details/106993425
【2】https://www.runoob.com/w3cnote/python-super-detail-intro.html

class A():
    def __init__(self,name,sex) -> None:
        self.name = name
        self.sex = sex
        print("A")
    def a(self):
        print("a")

class B(A):
    def __init__(self,name,sex) -> None:
        super().__init__(name,sex)
        print("B")
    def a(self):
        print("b")

b = B("123",1)
print(b.sex)
b.a()

最后一个小知识点:私有变量
1、单下划线开头的变量:

变量前的单下划线表示表面上私有 ;

但是其实这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

class Dog(object):
  _colour = '黑色' 
  age = 2 
dog = Dog() 
print(dog._colour)  # 对象点属性的时候虽然不会自动提示,但是你硬写上去也能打印出来

2、双下划线开头的变量:

双下划线开头的变量是类里面的私有变量,只能在类的内部访问,在外部是不允许访问的和修改的

class Dog(object):
    _colour = '黑色'
    __age = 2 
dog = Dog() 
print(dog.__age) # 结果报错 AttributeError: 'Dog' object has no attribute '__age'

但是可以使用方法去间接的获取和修改

class Dog(object):
    _colour = '黑色'
    __age = 2

    def get_age(self): return self.__age

    def set_age(self, age):
        self.__age = age

dog = Dog() print(dog.get_age())

dog.set_age(6) print(dog.get_age()) 

其实不用间接获取也能获取到,python只是把私有变量的名字给修改了

class Dog(object):
    _colour = '黑色'
    __age = 2

    def get_age(self): return self.__age

    def set_age(self, age):
        self.__age = age

dog = Dog() 
print(dog._Dog__age)  # 使用 _类名 + 变量名 当作属性去访问依然能访问到

所以,python里面没有真正意义上的私有变量

人类的单词应该是Human,我不应该用Person的,但是……,好吧,我懒得改了,摆烂了,将就着看嘛。码字超累的!


https://www.xamrdz.com/mobile/43s1907873.html

相关文章: