从pywifi的一个设计缺陷解析python类的成员访问

本文从pywifi库中的设计缺陷出发,探讨了Python类的成员访问,包括类属性与实例属性的区别、继承时的名称查找机制。作者通过实例详细分析了Python中属性成员的可见性和拥有性,以及类方法和实例方法的差异。此外,文章还对比了Python和C++在实现继承上的特点,强调了Python中继承的动态性和鸭子类型的灵活性。
摘要由CSDN通过智能技术生成

目录

1、缘起

2、群中的一次讨论

2.1 类与子类

2.1.1 从现象说起1:属性成员

2.1.2 从现象说起2:方法成员

2.1.3 小结

2.1.4 拓展:可见与拥有的关系

2.2 python类体系:一切皆对象,对象的访问可通过“可见+拥有”分析

2.3 这是一个彩蛋:什么是知识

3、C++和python在实现继承上的几点比较

3.1 “继承”概念

3.2 C++中的继承实现

3.3 python中的继承实现

3.4 网络小品:duck typing


1、缘起

前几天,我有一个设想,想用C语言写出一系列底层访问(获取与操作)WIFI的具体实现,然后封装成库引入到python中来,从技能上完成python和C/C++的连通。设想的施行条件VS2007、SDK、libcap、windump、python我都准备好(N,N,N年前就用过),不过还是在施行前从网上查了一下python操作WIFI现状,发现有个python库ctypes可以直接操作WINAPI,还发现有个pywifi包可以直接使用,于是就先深入一把ctypes,并pip install pywifi,看看这个包怎么样。(除pywifi外当然还有其他有意思的包)。

奔跑吧,兄弟:

pywifi 2020-05-22 15:30:47,918 INFO Get interface: Qualcomm Atheros AR956x Wireless Network Adapter
pywifi 2020-05-22 15:30:47,920 INFO iface 'Qualcomm Atheros AR956x Wireless Network Adapter' scans
pywifi 2020-05-22 15:30:52,935 INFO Scan found 11 networks.
pywifi 2020-05-22 15:30:52,942 INFO ---------------------------------->strProfileName: DXG3F
pywifi 2020-05-22 15:30:52,944 INFO   dot11Ssid: DXG3F
pywifi 2020-05-22 15:30:52,947 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:52,950 INFO   uNumberOfBssids: 1
pywifi 2020-05-22 15:30:52,952 INFO       Bssids: ['78:eb:14:d4:09:06']
pywifi 2020-05-22 15:30:52,955 INFO       sigFre: [(-47, 2472000)]
pywifi 2020-05-22 15:30:52,957 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:52,961 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:52,963 INFO   uNumberOfPhyTypes: 1
pywifi 2020-05-22 15:30:52,964 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:52,965 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:52,967 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:52,968 INFO   wlanSignalQuality (-100,-50)-->(0,100): 100
pywifi 2020-05-22 15:30:52,969 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:52,971 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:52,972 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:52,975 INFO   dwFlags: 6
pywifi 2020-05-22 15:30:52,975 INFO   dwReserved: 0
pywifi 2020-05-22 15:30:53,074 INFO ---------------------------------->strProfileName: CPS_Hotel
pywifi 2020-05-22 15:30:53,076 INFO   dot11Ssid: CPS_Hotel
pywifi 2020-05-22 15:30:53,078 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:53,080 INFO   uNumberOfBssids: 6
pywifi 2020-05-22 15:30:53,084 INFO       Bssids: ['00:1b:2f:ae:77:e5', 'c0:3f:0e:82:7f:3e', '00:18:4d:2b:c3:82', 'c0:3f:0e:82:7f:37', '00:24:b2:61:84:0f', '84:1b:5e:7b:b3:90']
pywifi 2020-05-22 15:30:53,086 INFO       sigFre: [(-91, 2412000), (-90, 2437000), (-85, 2437000), (-91, 2462000), (-90, 2422000), (-92, 2462000)]
pywifi 2020-05-22 15:30:53,088 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:53,091 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:53,094 INFO   uNumberOfPhyTypes: 2
pywifi 2020-05-22 15:30:53,096 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:53,099 INFO       dot11_phy_type_erp
pywifi 2020-05-22 15:30:53,101 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:53,103 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:53,107 INFO   wlanSignalQuality (-100,-50)-->(0,100): 30
pywifi 2020-05-22 15:30:53,109 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:53,111 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:53,113 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:53,115 INFO   dwFlags: 0
pywifi 2020-05-22 15:30:53,118 INFO   dwReserved: 0
pywifi 2020-05-22 15:30:53,252 INFO ---------------------------------->strProfileName: HUAWEI-421
pywifi 2020-05-22 15:30:53,254 INFO   dot11Ssid: HUAWEI-421
pywifi 2020-05-22 15:30:53,257 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:53,259 INFO   uNumberOfBssids: 1
pywifi 2020-05-22 15:30:53,261 INFO       Bssids: ['b0:89:00:09:56:fc']
pywifi 2020-05-22 15:30:53,263 INFO       sigFre: [(-86, 2462000)]
pywifi 2020-05-22 15:30:53,266 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:53,269 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:53,271 INFO   uNumberOfPhyTypes: 1
pywifi 2020-05-22 15:30:53,274 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:53,278 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:53,281 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:53,283 INFO   wlanSignalQuality (-100,-50)-->(0,100): 28
pywifi 2020-05-22 15:30:53,286 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:53,289 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:53,291 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:53,293 INFO   dwFlags: 0
pywifi 2020-05-22 15:30:53,295 INFO   dwReserved: 0
pywifi 2020-05-22 15:30:53,298 INFO ---------------------------------->strProfileName: DXG3F
pywifi 2020-05-22 15:30:53,301 INFO   dot11Ssid: DXG3F
pywifi 2020-05-22 15:30:53,303 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:53,305 INFO   uNumberOfBssids: 1
pywifi 2020-05-22 15:30:53,308 INFO       Bssids: ['78:eb:14:d4:09:06']
pywifi 2020-05-22 15:30:53,310 INFO       sigFre: [(-47, 2472000)]
pywifi 2020-05-22 15:30:53,313 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:53,316 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:53,318 INFO   uNumberOfPhyTypes: 1
pywifi 2020-05-22 15:30:53,320 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:53,322 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:53,325 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:53,328 INFO   wlanSignalQuality (-100,-50)-->(0,100): 100
pywifi 2020-05-22 15:30:53,330 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:53,332 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:53,334 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:53,337 INFO   dwFlags: 0
pywifi 2020-05-22 15:30:53,340 INFO   dwReserved: 0
pywifi 2020-05-22 15:30:53,343 INFO ---------------------------------->strProfileName: ChinaNet-2.4G-439
pywifi 2020-05-22 15:30:53,345 INFO   dot11Ssid: ChinaNet-2.4G-439
pywifi 2020-05-22 15:30:53,347 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:53,350 INFO   uNumberOfBssids: 1
pywifi 2020-05-22 15:30:53,352 INFO       Bssids: ['b0:ac:d2:0a:2e:12']
pywifi 2020-05-22 15:30:53,354 INFO       sigFre: [(-91, 2427000)]
pywifi 2020-05-22 15:30:53,357 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:53,360 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:53,363 INFO   uNumberOfPhyTypes: 1
pywifi 2020-05-22 15:30:53,365 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:53,367 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:53,369 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:53,372 INFO   wlanSignalQuality (-100,-50)-->(0,100): 12
pywifi 2020-05-22 15:30:53,375 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:53,378 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:53,380 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:53,383 INFO   dwFlags: 0
pywifi 2020-05-22 15:30:53,385 INFO   dwReserved: 0
pywifi 2020-05-22 15:30:53,389 INFO ---------------------------------->strProfileName: A Hide Network
pywifi 2020-05-22 15:30:53,391 INFO   dot11Ssid: A Hide Network
pywifi 2020-05-22 15:30:53,393 INFO   dot11BssType: dot11_BSS_type_infrastructure
pywifi 2020-05-22 15:30:53,395 INFO   uNumberOfBssids: 1
pywifi 2020-05-22 15:30:53,398 INFO       Bssids: ['80:3f:5d:5e:24:e3']
pywifi 2020-05-22 15:30:53,401 INFO       sigFre: [(-95, 2457000)]
pywifi 2020-05-22 15:30:53,403 INFO   bNetworkConnectable: True
pywifi 2020-05-22 15:30:53,406 INFO   wlanNotConnectableReason(if TRUE): 操作成功。
pywifi 2020-05-22 15:30:53,408 INFO   uNumberOfPhyTypes: 1
pywifi 2020-05-22 15:30:53,411 INFO   dot11PhyTypes:
pywifi 2020-05-22 15:30:53,414 INFO       dot11_phy_type_ht
pywifi 2020-05-22 15:30:53,417 INFO   bMorePhyTypes: False
pywifi 2020-05-22 15:30:53,419 INFO   wlanSignalQuality (-100,-50)-->(0,100): 4
pywifi 2020-05-22 15:30:53,423 INFO   bSecurityEnabled: True
pywifi 2020-05-22 15:30:53,426 INFO   dot11DefaultAuthAlgorithm: DOT11_AUTH_ALGO_RSNA_PSK
pywifi 2020-05-22 15:30:53,428 INFO   dot11DefaultCipherAlgorithm: DOT11_CIPHER_ALGO_CCMP
pywifi 2020-05-22 15:30:53,431 INFO   dwFlags: 0
pywifi 2020-05-22 15:30:53,433 INFO   dwReserved: 0
…

很容易了解到本机WIFI基本状态,以上面列出的最后显示的“A Hide Network ”为例。这是一个隐藏的WIFI网络,即电脑或手机上无法显示WIFI名称的那种,“A Hide Network”是我为了查询的需要而在日志输出语句中加的名称。网络类型是普通WIFI网络(区别于ad-hoc网络),网络中只有一个无线接入点(有可能是无线路由器、手机WIFI、电脑WIFI等),MAC为80:3f:5d:5e:24:e3,信号较弱,2.4G频段;接入点的WIFI物理组件使用802.11n协议,有安全机制,认证采用提前共享密钥的RSNA算法而加密的是CCMP算法,可被其他设备连接(因为是隐藏网络,所以要手动连接)。

别问我是怎么分析地这么头头是道,绝对属于我的是分析,而分析的内容有些是临时查WIN32 API、看无线网络安全基础、以及对一些关键词查字典式地查出的。

同时,也用Qtdesigner做了一个界面(只是引入UI,还没有加入wifi操作代码):

class MainGUI(QtWidgets.QMainWindow,Ui_MainWindow):
    def __init__(self, parent = None, flags = Qt.WindowFlags()):
        super().__init__(parent, flags)
        self.setupUi(self)
    def WiFipreconnect(self):pass
    def WiFiscan(self,INobj):pass
    def WiFiconnect(self,INobj):pass
if __name__=="__main__":
    app=QtWidgets.QApplication(sys.argv)
    window=MainGUI()
    window.show()
    try:
     sys.exit(app.exec_())
    except: pass

如果你也用过pywifi,可能会奇怪之前列出的wifi数据,原程序输出不是这样的,那是因为我已经做了我想要的改动。

在看代码期间,发现一个有趣的问题,原来代码:

片段一:

class Interface:
    """Interface provides methods for manipulating wifi devices."""
    """
    For encapsulating OS dependent behavior, we declare _raw_obj here for
    storing some common attribute (e.g. name) and os attributes (e.g. dbus
    objects for linux)
    """
    _raw_obj = {}
    _wifi_ctrl = {}
    _logger = None
    def __init__(self, raw_obj):
        self._raw_obj = raw_obj
        self._wifi_ctrl = wifiutil.WifiUtil()
    self._logger = logging.getLogger('pywifi')

片段二:

class PyWiFi:
    """PyWiFi provides operations to manipulate wifi devices."""
    _ifaces = []
    _logger = None
    def __init__(self):
        self._logger = logging.getLogger('pywifi')
    def interfaces(self):
        """Collect the available wlan interfaces."""
        self._ifaces = []
        wifi_ctrl = wifiutil.WifiUtil()
        for interface in wifi_ctrl.interfaces():
            iface = Interface(interface)
            self._ifaces.append(iface)
            self._logger.info("Get interface: %s", iface.name())
        if not self._ifaces:
            self._logger.error("Can't get wifi interface")
        return self._ifaces

我不知道pywifi包的发布者本来用意,但很明显,这两个片段都存在类属性与实例属性的设计矛盾。这实际上很容易发现。

这样的矛盾在现有pywifi包的设计架构上,或者说在几百行以内的python代码中不会导致什么很大的漏洞。如果要基于pywifi做进一步开发,则要警惕。

2、群中的一次讨论

2.1 类与子类

2.1.1 从现象说起1:属性成员

与这个设计缺陷相对应的,是那天在群里的一个讨论。讨论的内容简要还原如下(我用的是python 3.6.5):

>>> class parent:
	_d={}
	def __init__(self):
		self._d['a']=0
		self._d['b']=0
		self._d['c']=0		
>>> class A(parent):
	def init(self):
		self._d['a']=1
		self._d['b']=1
		self._d['c']=1
>>> class B(parent):
	def init(self):
		self._d['a']=2
		self._d['b']=2
		self._d['c']=2	
>>> a=A()
>>> b=B()
>>> a.init()
>>> l=[b,a]
>>> for i in l:print(i._d)
{'a': 1, 'b': 1, 'c': 1}
{'a': 1, 'b': 1, 'c': 1}

有群友提问,为什么输出结果都一样?

原因很简单:子类实例对象a和b所谓“继承”来的_d实际上是同一个“外部”(不拥有但可见可访问)对象。

请仔细观察下面经我粗暴标示的属性和方法:

>>> A.__dict__

mappingproxy({'__module__': '__main__', 'init': <function A.init at 0x0000024BF7073D08>, '__doc__': None})

>>> dir(A)

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_d', 'init']

>>> a.__dict__

{}

>>> dir(a)

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_d', 'init'

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值