Python面向对象知识汇总

面向对象知识汇总

1.类与对象

1
2
对象=属性(特征)+方法(行为)
类:在python中,把具有相同属性和方法的对象归为一个类(class

2.属性查找

1
先找对象自己,找不到去类中找,再找不到就在类的__mro__列表中查找(Python2 和Python3 一个是深度优先一个是广度优先)  

3.类属性和对象属性

1
2
类属性指的是类对象所绑定的属性,在类加载的时候,就已被分配了内存只有一份,所有new出来的对象都共享此属性。
而对象的属性属于单个实例化的对象,每new一个实例就在堆内存中创建一份,就等于多个拷贝,占内存多,但比较灵活,自己修改自己的属性值,互不影响。  

4.对象的绑定方法

1
2
1.绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即self
2.类也可以来调用绑定方法,但是类调用就是普通函数,有几个参数就要传几个参数  

5.函数和方法

1
2
1、函数要手动传self,方法不用传self。
2、如果是一个函数,用类名去调用,如果是一个方法,用对象去调用。  

6.类的继承(python支持多继承)

1
2
1.python允许在一个或多个类的基础上生成新的类,新的类可以使用父类的一些属性和方法,这个过程就叫做继承。
2.python继承最大的作用就是为了减少代码。    

7.派生

1
派生就是子类在继承父类的基础上衍生出新的属性。子类中独有的,父类中没有的;或子类定义与父类重名的东西。子类也叫派生类。  

8.super()特殊的对象

1
super()避免了基类的显式调用  

9.多继承下的super(FatBossGril.mro)

1
多继承上,super方法能保证每个父类的方法只会执行一次  

10.组合

1
属性的值是指向另外一个类的对象   

11.多态与多态性

1
2
1.多态指的是一类事物有多种形态
2.多态性:一种调用方式,不同的执行效果  

12.封装

1
2
3
实际python中的封装只是一个约定
第一层面的封装:类就好像一个袋子,这就是一种封装
第二层面的封装:类中定义私有的,只有类内部使用,通过_或__隐藏对象的属性和实现细节,仅对外提供公共访问方式。  

13.property

1
加了@property后,可以用调用属性的形式来调用方法,后面不需要加()  

14.类方法

1
2
3
1、对象方法:通常第一个参数self,由类实例化后的对象调用,会将对象自动传入到self
2、类方法:使用@classmethod,第一个参数是cls,是对当前类做的额外的处理,类方法需要用类去调用,而不是实例对象调用,会将类自动传入到cls
3、静态方法:使用@staticmethod装饰器,默认没有参数  

15.isinstance与type

1
2
isinstance() 会认为子类是一种父类类型,考虑继承关系。
type() 不会认为子类是一种父类类型,不考虑继承关系。  

16.反射getattr,setattr,hasattr,delattr

1
2
3
4
1 hasattr:判断一个对象里面是否有特定属性或者方法,返回BOOL值,有特性返回True, 否则返回False。需要注意的是属性或者方法是字符串要用引号括起来。
2.getattr:获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,可以在后面添加一对括号。
3.setattr:给对象的属性赋值,若属性不存在,先创建再赋值。
4.delattr:删除对应的属性  

17 

18.initnew__

1
2
1.__new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。
2.__init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候。是一个实例方法。也就是: __new__先被调用,__init__后被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数。

19.元类

1
元类就是Python在背后用来创建所有类的类。一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元类

20.元类和object的区别

1
2
1.type:所有类的类,但是继承object
2.object:所有类的父类,同时由type生成  

21.__setitem__、__getitem__、__delitem__

1
2
3
__setitem__:每当属性被赋值/更新的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
__getitem__:在使用点调用且属性不存在时会调用该方法
__delitem__:当删除属性时调用该方法  

1)__getitem__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#访问不存在的属性时会调用该方法
 
class Zoo:
     def __getitem__(self, name):
         print("xxxxxxxxxxx")
         return 6666
          
zoo = Zoo()
x = zoo["name"]
print(x)
----------------------------------------------------------------------------
结果:
xxxxxxxxxxx
6666 

2)__setitem__

1
2
3
4
5
6
7
8
9
10
11
12
13
#每当属性被赋值的时候都会调用该方法 ,因此不能再该方法内赋值 self.name = value 会死循环
 
class Zoo:
     def __setitem__(self, key,value):
         print("%s 是 %s"%( key,value))
         print(self.__dict__)
zoo = Zoo()
zoo["ALEX"] = 'SB'  #注意结果不会放到__dict__中
----------------------------------------------------------------------------
结果:
ALEX 是 SB
{}

3)__delitem__

1
2
3
4
5
6
7
8
9
10
11
#删除属性时调用该方法
 
class Zoo:
     def __delitem__(self, key):
         print("谁特么让你删 %s 的" % key)
          
zoo = Zoo()
del zoo["alex"]
----------------------------------------------------------------------------
结果:
谁特么让你删 alex 的

4).示例,使用__setattr__ 和 __getattr__ 实现类属性的赋值类型限制,只允许整形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Foo:
<br>
    def __getattr__(self, item):
        print(item)
        return 99
 
    def __setattr__(self, key, value):
        if isinstance(value,int):
<br>            '''错误的方法<br>        1.使用反射
                setattr(self,key,value)  # setattr本质还是调用了self.key=value,会发生死循环<br>        2.使用self.赋值
                self.age = value           # 与上类似,也会发生死循环<br>            '''
            # 可以使用的方式<br>            # 1.利用__dict__赋值
            # self.__dict__[key] = value   # 这种方式解决递归问题<br>            # 2.利用其他类__setattr__方法
            # 普通函数,有几个参数,就传几个参数
            object.__setattr__(self,key,value)
        else:
            raise Exception('不让放')
    def printsize(self):
        print(self.__size)
 
 
f = Foo()
print(f.__dict__)
# f.age = '19'  # 放的age必须是数字
# f.age = 19  # 放的age必须是数字
# print(f.age)
#
#
# object.__setattr__(f,'_Foo__size',178) #把属性直接设置为私有属性
#
# print(f.size)
# f.printsize()
# print(f._Foo__size)
 
 
# print(f.xxx)
# print(f.xx)

不使用字典实现 中括号[  ] 赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Foo:
    def __setitem__(self, key, value):
        setattr(self, key, value)
        # object.__setattr__(self,key,value)
 
    def __getitem__(self, item):
        return getattr(self, item)
 
 
f = Foo()
f.name = 'lqz'
print(f.name)
print(f['name'])
f['age'] = 19
print(f.age)
print(f['age'])

22.单例模式实现三个方法:

1)类方法实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import settings
  
class Mysql:
    __instance=None
    def __init__(self,host,port):
        self.host=host
        self.port=port
  
    @classmethod
    def singleton(cls):
        if not cls.__instance:
            cls.__instance=cls(settings.HOST,settings.PORT)
        return cls.__instance
  
obj1=Mysql('1.1.1.2',3306)
obj2=Mysql('1.1.1.3',3307)
print(obj1 is obj2) #False
  
obj3=Mysql.singleton()
obj4=Mysql.singleton()
print(obj3 is obj4) #True  

2)定制元类实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import settings
  
class Mymeta(type):
    def __init__(self,name,bases,dic): #定义类Mysql时就触发
        # 事先先从配置文件中取配置来造一个Mysql的实例出来
        self.__instance = object.__new__(self)  # 产生对象
        self.__init__(self.__instance, settings.HOST, settings.PORT)  # 初始化对象
  
    def __call__(self, *args, **kwargs): #Mysql(...)时触发
        if args or kwargs: # args或kwargs内有值
            obj=object.__new__(self)
            self.__init__(obj,*args,**kwargs)
            return obj
        return self.__instance
  
class Mysql(metaclass=Mymeta):
    def __init__(self,host,port):
        self.host=host
        self.port=port
  
obj1=Mysql() # 没有传值则默认从配置文件中读配置来实例化,所有的实例应该指向一个内存地址
obj2=Mysql()
obj3=Mysql()
print(obj1 is obj2 is obj3)
obj4=Mysql('1.1.1.4',3307) 

3)装饰器实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import settings
  
def singleton(cls): #cls=Mysql
    _instance=cls(settings.HOST,settings.PORT)
  
    def wrapper(*args,**kwargs):
        if args or kwargs:
            obj=cls(*args,**kwargs)
            return obj
        return _instance
    return wrapper
  
  
@singleton # Mysql=singleton(Mysql)
class Mysql:
    def __init__(self,host,port):
        self.host=host
        self.port=port
  
obj1=Mysql()
obj2=Mysql()
obj3=Mysql()
print(obj1 is obj2 is obj3) #True
  
obj4=Mysql('1.1.1.3',3307)
obj5=Mysql('1.1.1.4',3308)
print(obj3 is obj4) #False  

  

  

 

 

 

posted @   百衲本  阅读(149)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
cnblogs_post_body { color: black; font: 0.875em/1.5em "微软雅黑" , "PTSans" , "Arial" ,sans-serif; font-size: 15px; } cnblogs_post_body h1 { text-align:center; background: #333366; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 23px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h2 { text-align:center; background: #006699; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 20px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h3 { background: #2B6695; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 18px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } 回到顶部 博客侧边栏 回到顶部 页首代码 回到顶部 页脚代码
点击右上角即可分享
微信分享提示