一 基本概念

OO:面向对象(Object-Oriented,简称OO),是一种解决问题的思想。以对象为核心,不关注解决问题的细节,只关注结果。整个过程可以复用

PO:面向过程(Procedure Oriented,简称PO),是一种解决问题的思想。以过程为核心,关注解决问题的步骤,整个过程不好复用

面向对象软件开发要经历的三个阶段:面向对象编程(OOP)和面向对象分析(OOA)面向对象设计(OOD)。它以类与对象两种数据结构来组织代码的,并以封装、继承、多态 三个特性作为基础设计与实现代码的

OOP:面向对象编程(Object-Oriented Programming,简称 OOP)是一种基于面向对象思想为指导编写程序的一种编程风格或者编程规范

POP:面向过程编程(Procedure-Oriented Programming,简称POP)则是一种基于面向过程思想为指导编写程序的一种编程风格或者编程规范

### 面向对象编程是以类(Class)与对象(Object或Instance)2种数据结构组织代码的。###

类:是一种现实生活中个体特征相似的抽象的集体概念

对象:是类的一员,是类的具体(实例)

二 类

类的声明
 
class 类名(object):
"""类的说明文档"""
属性 = 数据
@classmethod
def 类方法名(cls[, 参数列表]):
#函数代码,一般编写用于操作类属性的代码

问题:类有类属性和类方法,对象有实例属性和实例方法,而且都写在同一个类中,什么时候该声明类属性/类方法?什么时候声明实例属性/实例方法呢?

解答:有些变量,是所有对象都共用拥有的,就把这些变量作为类属性进行声明,达到节约内存的作用。

有些变量是每一个个体的数值都不一样的,那么这些变量就应该作为实例属性进行声明。

同理,操纵类属性的方法,就应该采用类方法进行声明,而操作实例属性的,就应该采用实例方法来声明。


!!
# 对象是由类创建出来的,所以对象的属性和方法基本都是写在类里面的。在类创建对象以后,提供给对象。
# 类有类属性和类方法,对象有实例属性和实例方法,而且都写在同一个类中
class 类名(object):
"""类的说明文档"""
# 每一个对象,如果有属性,则属性一般写在__init__构造方法中
def __init__(self, 参数1, 参数2):
"""构造方法"""
# 构造方法,是一个固定函数名的魔术实例方法,在初始化对象时自动运行,并把类后面的参数提取作为自己的参数
# 在构造方法中的代码,一般就是对象的实例属性声明的代码,当然,也可以编写一些对象初始化时就要执行的代码
self.参数1 = 参数1
self.参数2 = 参数2
# 实例方法,有别于类方法,不需要加上@classmethod
# 对象的每个实例方法必须有至少一个参数,而且第一个参数是固定必须叫self,代表当前对象
def 实例方法名(self,参数x):
# 在对象中如果要修改或访问对象的其他方法或属性,需要使用self.开头作为前缀,否则会变成访问全局变量。
print(self.参数1)=参数x
 类的命名规则  

三种变量的命名写法:
1. 大驼峰式,每个单词首字母大写
Goods、Student、MiddleStudent

2. 小驼峰式,首个单词首字母小写,其他单词首字母全部大写
goods、middleStudent

3. 匈牙利写法,拼接符把多个单词拼接的写法
middle_student
top_menu
top-menu

 
类的操作
class Dog(object):
# 类属性列表
eye_length = 2
leg_length = 4
max_age = 12

@classmethod
def run(cls):
print(f"{cls.leg_length}条腿跑....")

@classmethod
def eat(cls, food):
print(f"边吃{food},边{cls.wag_tail()}")

@classmethod
def wag_tail(cls):
return "摇尾巴...."
# 类属性的调用
print(Dog.eye_length)

# 修改类属性,类似修改变量,区别在于类属性是有前缀的
Dog.max_age = 30
print(Dog.max_age)

# 类方法的调用
print( Dog.wag_tail() ) # 摇尾巴....
Dog.run() #4条腿跑....
Dog.eat("狗粮") #边吃狗粮,边摇尾巴....
 

 三 对象

对象的实例化
"""先声明类,后调用类创建对象,就可以完成实例化的过程"""
class Person(object):
"""人类"""
pass

print(Person, id(Person)) #<class '__main__.Person'> 140276104610512

"""一个类可以实例化1个或多个对象"""
xiaoming = Person()
print(xiaoming, id(xiaoming))#<__main__.Person object at 0x10b758f70> 4487221104
xiaohong = Person()
print(xiaohong, id(xiaohong))#<__main__.Person object at 0x10b758ee0> 4487220960

# 查看类型
print(type(xiaoming))#<class '__main__.Person'>

# 判断一个对象是否是否某个类的实例
print( isinstance(xiaoming, Person)) # True
对象的操作
#对象是由类创建出来的,所以对象的属性和方法基本都是写在类里面的。在类创建对象以后,提供给对象。
# 类有类属性和类方法,对象有实例属性和实例方法,而且都写在同一个类中
class Dog(object):
# 类属性列表
eye_length = 2
leg_length = 4
max_age = 30
tail_length = 1

def __init__(self, name, age):
"""实例属性列表"""
self.name = name
self.age = age

@classmethod
def run(cls):
# 在类中如果要修改或访问当前类的其他类方法或类属性,需要使用cls.开头作为前缀,否则会变成访问全局变量。
print(f"{cls.leg_length}条腿交叉来回地跑....")

@classmethod
def wag_tail(cls):
return "摇尾巴...."

def get_guide(self, where):
print(f"导盲去{where}")


xiaoqiang = Dog("小强", 7)
# 对象访问类属性
print(f"我家的狗[{xiaoqiang.name}]今年{xiaoqiang.age}岁了,但是它能活{xiaoqiang.max_age}年。")

"""不同对象所有拥有的类属性和类方法,是一模一样的。而且内存地址也是一样的。"""
Dog.max_age = 50
print(f"我家的狗[{xiaoqiang.name}]今年{xiaoqiang.age}岁了,但是它能活{xiaoqiang.max_age}年。")

"""对象无法修改类属性的值,下方会变成新增属性"""
xiaoqiang.max_age = 50
print(f"我家的狗[{xiaoqiang.name}]今年{xiaoqiang.age}岁了,但是它能活{xiaoqiang.max_age}年。")

# 给类新增属性
Dog.skill_list = ["打架", "拆迁"]
print(f"我家的狗[{xiaoqiang.name}]今年{xiaoqiang.age}岁了,擅长{xiaoqiang.skill_list}。")

# 证明不同对象所有拥有的类属性和类方法,是一模一样的。而且内存地址也是一样的。
print(id(Dog.skill_list) )
print(xiaoqiang.skill_list)
# 同一个类实例化出来的不同对象, 所拥有的实例属性和实例方法,都是相互独立,互不干扰

四 静态方法

有些方法,本身在函数内部既没有调用到类属性,也没有调用到实例属性,静态方法的使用,仅仅是一种规范。可以把不操作类或对象数据的方法,使用实例方法或类方法来声明。

"""
同一个类下所有对象共有的属性,就是类属性,
同一个类下所有对象独有的属性,就是实例属性
类方法操作类属性,实例方法操作实例属性
"""
class Dog(object):
    # 类属性列表
    eye_length = 2
    leg_length = 4
    tail_length = 1

    def __init__(self, name, age):
        """实例属性列表"""
        self.name = name
        self.age = age
        self.skill_list = []

    def learn_skill(self, skill):
        self.skill_list.append(skill)

    def get_skill_list(self):
        return self.skill_list

    @classmethod
    def wag_tail(cls):
        return f"{cls.tail_length}条尾巴不断摇晃..."

    # 使用@staticmethod表示当前方法是一个不需要传递当前对象或当前类的静态方法,
    # 内部不会操作到当前类属性或实例属性,仅仅是一个存在关联性而放进来的。
    @staticmethod
    def eat(food):
        print(f"吃{food}")

xiaobai = Dog("小白", 3)
print(xiaobai.get_skill_list()) #[]

xiaobai.learn_skill("变身")
print(xiaobai.get_skill_list()) #['变身']

print(xiaobai.wag_tail())#1条尾巴不断摇晃...

# 静态方法声明了以后,不仅对象可以调用,类也可以调用
xiaobai.eat("寿司") #吃寿司
"""
静态方法的声明,与实例方法、类方法不一样,实例方法和类方法,在声明时都需要保留一个参数作为当前类或当前对象的变量,而静态方法不会有。
同时,实例方法、类方法在调用时和静态方法是一样,实例方法的self,类方法的cls不需要我们手动传递,python语法会自动传递。
"""
posted on 2022-04-21 20:23  大明花花  阅读(40)  评论(0编辑  收藏  举报