python面向对象学习笔记

python面向对象Object Oriented Programming

参考资料

https://pythonhowto.readthedocs.io/zh_CN/latest/object.html?utm_source=pocket_saves#id6

基本概念

python中万物皆对象,即object

object对象

每一个对象,无论是数值、变量、数据类型、类、实例、函数等,都包含下面三个属性

  • id():获取对象的内存地址
  • type() == .__class__:获取对象的数据类型
  • print():打印对象的值
# 1.值:ID,类型,值
print(id(1), type(1), 1)		# 140716375728936 <class 'int'> 1
# 2.变量:ID,类型,值
a = 2
print(id(a), type(a), a)		# 140716375728968 <class 'int'> 2
# 3.数据类型::ID,类型,值
print(id(int),type(int),int)	# 140716374253104 <class 'type'> <class 'int'>
# 4.type:ID,类型,值
print(id(type),type(type),type)	#140716374265744 <class 'type'> <class 'type'>
# 5.自定义类:ID,类型,值
class Foo: pass
print(id(Foo), type(Foo), Foo)	# 2193622277152 <class 'type'> <class '__main__.A'>
# 6.实例:ID,类型,值
f = Foo()
print(id(f), type(id), id)		# 2193590183440 <class '__main__.A'> <__main__.A object at 0x000001FEBC29E610>
# 7.函数:ID,类型,值
def hello(): pass
print(id(hello),type(hello),hello)
1320842727232 <class 'function'> <function hello at 0x00000133885C8F40>
  • __bases__:当前对象的直接父类

    a = 1
    # 1.数据类型的直接父类
    print(int.__bases__)	# (<class 'object'>,)
    # 2.type的直接父类
    print(type.__bases__)	# (<class 'object'>,)
    # 3.变量的直接父类
    print(a.__bases__)
    ------------------------------------------
    Traceback (most recent call last):
      File "<pyshell#4>", line 1, in <module>
        a.__base__
    AttributeError: 'int' object has no attribute '__base__'.
    

type类型

python中万物皆对象,每个对象object都有type,type也自然就离不开对象object。

type决定了object的可执行操作,如‘type=int’,则其接收的数据必为整型,也只能进行整数的操作

class类

由下面的代码,我们知道定义一个类class,其实就是定义了一个新类型type的对象object

# 5.自定义类:ID,类型,值
class Foo: pass
print(id(Foo), type(Foo), Foo)	# 2193622277152 <class 'type'> <class '__main__.A'>

class其实就是一种type,只不过type通常是python内置的数据类型,class是指用户自定义的一种类型。

  • __bases__:当前对象的直接父类

    class A: pass
    class B: pass
    
    class C(A,B): pass
    print(A.__bases__)
    print(B.__bases__)
    print(C.__bases__)
    -------------------------------
    (<class 'object'>,)
    (<class 'object'>,)
    (<class '__main__.A'>, <class '__main__.B'>)
    
  • issubclass(A,B):判断A是不是B的子类

    print(issubclass(C,A))
    print(issubclass(C,B))
    ---------------------------------
    True
    True
    
  • 利用type动态创建一个类:

    type(name, bases, dict):

    • name:类的名称
    • bases:基类元祖
    • dict:定义属性和函数
    # 利用class定义类
    class X:
        name = haha
        def print_name(self):
            print(self.name)
    
    # 利用type等价定义类
    def print_name(self):
        print(self.name)
    type('X', (object,), {'name': haha, 'print_name': print_name})
    

Instance实例

type 与 class,object 与 instance其实都是不同情镜下的同一种东西

  • 1是int类型(type)的对象(object)
  • 1是int类(class)的对象(object)
  • 1是int类型(type)的实例(instance)
  • 1是int类(type)的实例(instance)

isinstance(obj,class):判断obj是不是class的实例

  • obj:实例对象
  • class:类
class Foo(): pass

f = Foo()
print(isinstance(f,Foo))	# True
print(ininstance(f,object))	# True

区分type()和isinstance():

  • type不考虑继承关系
  • instance考虑继承关系

object 和 type

object和type是python中的顶级元素

  • python中万物皆对象,即object是所有对象的基类,而它的类型是type,type也继承于object。
  • python中的对象分为两类:
    • 数据型对象(Type):int,str,list,dict,tuple…
    • 非数据型对象(Non-Type):数值,变量,实例
  • 数据型对象除了是object的子类,也是type类型的实例
  • 而非数据型对象是数据型对象的实例。

类和对象

类属性

1)含义:类中封装在函数外,一般定义在类的头部的变量

2)访问:通过类名或者实例访问

class Student():
    school = "三中"
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
# 1.类名访问
print(Student.school)	# 三中
# 2.实例访问
s = Student("petty",18)
print(s.school)			# 三中

3)改值:

  • 直接对类属性赋值,则该类的所有实例对象的类属性都会修改

    Student.school = "一中"
    print(Student.school)
    
  • 对实例对象的属性赋值,修改过程中会进行拷贝,该实例的类属性将脱离类的属性,实现了属性的解绑定,把原来类属性覆盖了,该属性成为了实例的私有属性,其他实例不会受影响。

    s = Student("petty",18)
    s.school = "一中"
    print(s.chool)
    

类私有属性__

1)定义:变量名前加上两个下划线__

2)访问:不能通过类名或者实例直接访问,只能通过类方法访问。或者可以通过实例._类名__属性的方式访问,但是这种写法不规范

class Student:
    __school = "三中"
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    @classmethod
    def get_school(cls):
        return cls.__school
    
    @classmethod
    def set_school(cls, school):
        cls.__school = school
        
# 1.类名访问
print(Student.__school)
# 2.实例访问
s = Student("petty",18)
print(s.__school)
# 3.类方法访问
print(s.get_school())
print(Student.get_school())
# 4._类名__属性
print(s._Student__school)

3)修改:修改过程不会拷贝,在内存中只有一份,通过类方法修改后,再创建该类的实例对象时,其私有属性会改变

s1 = Student("petty",18)
s2 = Student("alice",19)
print(s1.get_school())
print(s2.get_school())
s.set_school("一中")
print(s1.get_school())
print(s2.get_school())
print(Student.get_school())

>>>
三中
三中
一中
一中
一中

类方法classmethod

1)定义:类中定义的函数,并添加装饰器@classmethod,必须参数为cls,即类本身

2)调用:可通过类名或者实例调用

class Student:
    __school = "三中"
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    @classmethod
    def get_school(cls):
        return cls.__school
    
    @classmethod
    def set_school(cls, school):
        cls.__school = school
        

s = Student("petty",18)
# 1.实例访问
print(s.get_school())
# 2.类名访问
print(Student.get_school())

类静态方法staticmethod

1)定义:类中定义的函数,并添加装饰器@staticmethod

2)调用:类名或者实例调用

class Student:
    ......
    @staticmethod
    def static_get():
        print("This is a class static method")

s = Student("petty",18)
Student.static_get()
s.static_get
>>>
This is a class static method
This is a class static method

3)注意:无论是类方法还是类的静态方法都只能通过类名加 ‘.’ 的方式调用,不能间接调用它们

class Student():
    .....
    @classmethod
    def get_school(cls):
        return cls.__school

    func_map = {'get_school':get_school}

    def call_func_map(self):
        self.get_school()	# 可用
        self.func_map['get_school']()	#报错

s = Student("petty",18)
s.call_func_map()

>>>
三中
TypeError: 'classmethod' object is not callable

查看类属性和方法dir

dir()内建函数:用于获取任意对象的所有属性和方法

class Student:
    __school = "三中"
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    @classmethod
    def get_school(cls):
        return cls.__school
    
    @classmethod
    def set_school(cls, school):
        cls.__school = school
        
    @staticmethod
    def static_get():
        print("This is a class static method")

dir(Student)
>>>
['_Student__school', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_school', 'set_school','static_get']
  • 其中大部分继承了object的属性与方法

  • 自定义的属性与方法有:

    ['_Student__school',  '__init__', 'get_school', 'set_school', 'static_get']
    
  • 可以看到私有属性的命名方式比较特别,其在原定义的变量名上加上了_类名的前缀

print(type(Student.__init__))
print(type(Student.get_school))
print(type(Student.set_school))
print(type(Student.static_get))

>>>
<class 'function'>
<class 'method'>
<class 'method'>
<class 'function'>

:类中没有明确声明为类方法的函数类型均为 function,只有类方法的类型为 method

方法与属性总结

# 1) 类名调用:带参数cls
# 2) 实例调用:带参数self,即实例对象本身

class Student:
    # 类属性
    city = "北京"
    # 私有属性
    __school = "三中"

    # 魔法方法:初始化函数
    def __init__(self, name, age, id):
        # 实例属性
        self.name = name
        self.age = age
        # 实例私有属性
        self.__id = id

    # 类方法:参数cls为类本身Student
    # 类方法获取私有属性
    @classmethod
    def cls_get_school(cls):
        return cls.__school

    # 类方法设置私有属性
    @classmethod
    def cls_set_school(cls, value):
        cls.__school = value
        print("类方法设置私有属性")

    # 静态方法,不带参数
    @staticmethod
    def static_get():
        print("静态方法不带参")


    # 实例方法:参数self为实例对象本身
    # 实例方法访问实例私有属性
    def get_id(self):
        return self.__id

    # 实例方法设置实例私有属性
    def set_id(self, value):
        self.__id = value


# 1.创建实例对象,name="petty", age=19, id=1
s = Student("petty", 19, 1)
print("类:", dir(Student))
print("实例:", dir(s))
# 下面只展现我们自定义的部分,有关object的给省略了
# 类: ['_Student__school', 'city', 'cls_get_school', 'cls_set_school', 'get_id', 'set_id', 'static_get']
# 实例: ['_Student__id', '_Student__school', 'age', 'city', 'cls_get_school', 'cls_set_school', 'get_id', 'name', 'set_id', 'static_get']
# 实例比类多了 name, age, _Student__id


print("*"*20)
# 2.访问属性
# 2.1 访问类属性
print("类名访问类属性:城市", Student.city)  # 类名访问类属性:城市 北京
print("实例访问类属性:城市", s.city)  # 类名访问类属性:城市 北京
print("*"*10)


# 2.2 访问类私有属性
# print("类名访问类私有属性:学校", Student.__school)   # type object 'Student' has no attribute '__school'
# print("实例访问类私有属性:学校", s.__school)         # 'Student' object has no attribute '__school'


# 2.3 访问实例属性
# print("类名访问实例属性:姓名", Student.name)  # type object 'Student' has no attribute 'name'
print("实例访问实例属性:姓名", s.name)          # 实例访问实例属性:姓名 petty
print("*"*10)


# 2.4 访问实例私有属性
# print("类名访问实例私有属性:id", Student.__id)    # type object 'Student' has no attribute '__id'
# print("实例访问实例私有属性:id", s.__id)            # 'Student' object has no attribute '__id'

print("*"*20)



# 3.调用方法
# 3.1 调用类方法
print("类名-调用类方法:获取类私有属性-学校", Student.cls_get_school())  # 类名-调用类方法:获取类私有属性-学校 三中
Student.cls_set_school("一中")                                     # 类方法设置私有属性
print("类名-调用类方法:获取类私有属性-学校", Student.cls_get_school())  # 类名-调用类方法:获取类私有属性-学校 三中

print("实例-调用类方法:获取类私有属性-学校", s.cls_get_school())        # 实例-调用类方法:获取类私有属性-学校 一中


print("*"*10)
# 3.2 调用静态方法
print("类名-调用静态方法", Student.static_get())    # 静态方法不带参 类名-调用不带参静态方法 None
print("实例-调用静态方法", s.static_get())          # 静态方法不带参 类名-调用不带参静态方法 None


print("*"*10)
# 3.3 调用实例方法
# print("类名-调用实例方法", Student.get_id())    # Student.get_id() missing 1 required positional argument: 'self'
print("实例-调用实例方法,获取实例私有属性id", s.get_id())

动态绑定类属性和方法【类】

1)何为动态?

即不在类定义中绑定的属性和方法,而是在类定义外通过类.的方式绑定属性和方法。若该属性名或方法名已存在,则会覆盖原有值;反之,则重新创建该属性并赋值。

2)动态绑定类属性

# 类
class Student(): pass


# 1.动态绑定属性
Student.school = "三中"
# 2.类名访问类属性
print(Student.school)
# 3.实例访问类属性
s = Student()
print(s.school)


>>>
三中
三中

3)动态绑定类方法

# 类
class Student(): pass
# 函数
def hello(self): print("hello")
    
    
# 1.动态绑定方法
Student.hello = hello
# 2.类名调用类方法
Student.hello()
# 3.实例调用类方法
s = Student()
s.hello()


>>>
hello
hello

动态绑定属性和方法【实例】

同样可以对一个对象进行动态添加属性和方法,只是它们均为这个对象所私有,不会影响类的其他实例对象。如果对象方法已经存在,则被覆盖。

class Student: pass


# 1.动态绑定对象属性
s = Student()
s.name = "alice"
print("动态绑定实例属性后,实例访问属性",s.name)
print("动态绑定实例属性后,类访问属性",Student.name)

# 2.动态绑定对象方法
def say_goodbye(self): print("goodbye")
    
from types import MethodType
s = Student()
s.say_goodbye = MethodType(say_goodbye)	# 

对象中的函数被称为 method 方法类型,普通函数类型为 function,这里需要借助 types 模块中的 MethodType() 将一个函数转化为一个对象的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值