неожиданная обработка аргументов Python3 по умолчанию - PullRequest
1 голос
/ 29 октября 2019

В моем проекте с открытым исходным кодом https://github.com/WolfgangFahl/play-chess-with-a-webcam я использую класс Warp (см. https://github.com/WolfgangFahl/play-chess-with-a-webcam/blob/master/src/WebApp.py и фрагмент кода ниже), чтобы отслеживать точки деформации для шахматной доски. Идея состоит в том, что пользователь нажимает одну точку трапеции за другой, пока не станет известна позиция шахматной доски на изображении. Затем изображение «деформируется» соответственно. Чтобы вернуться к не деформированному изображению, другой щелчок сбросит деформацию.

Эта логика реализована путем подсчета количества точек, уже добавленных в «список точек». По умолчанию для списка точек задано пустое значение, но его также можно указать с помощью командной строки.

это соответствующий фрагмент конструктора:

def __init__(self,pointList=[],rotation=0,bgrColor=(0, 255, 0)):
       self.pointList = pointList
       self.updatePoints()

Теперь имеется тестирование для тестирования этого класса. см. https://github.com/WolfgangFahl/play-chess-with-a-webcam/blob/master/src/test_Warp.py и приведенный ниже код.

При непосредственном запуске этого кода

python3 test_Warp.py

код успешно работает на разных машинах, версиях python3.x и travis. Но если я запускаю весь набор тестов проекта

scripts/test

Поведение зависит от того, имеет ли функция getTestWarp:

def getTestWarp():
    warp=Warp([])

, которая работает. Или:

def getTestWarp():
    warp=Warp()

, что приводит к сбою тестового набора, если ранее выполнялись другие тесты. Таким образом, контекст имеет значение.

Как это может быть?

Является ли это ошибкой или ожидаемым поведением и может быть объяснено каким-то специфическим для Python способом обработки параметров по умолчанию иатрибуты экземпляра?

Класс деформации

class Warp(YamlAbleMixin,JsonAbleMixin):
    """ holds the trapezoid points to be use for warping an image take from a peculiar angle """

    # construct me from the given setting
    def __init__(self,pointList=[],rotation=0,bgrColor=(0, 255, 0)):
       self.rotation=rotation
       self.bgrColor=bgrColor
       self.pointList = pointList
       self.updatePoints()

    def rotate(self,angle):
       self.rotation=self.rotation+angle
       if self.rotation>=360:
         self.rotation=self.rotation % 360

    def updatePoints(self):
      pointLen=len(self.pointList)
      if pointLen==0:
        self.points=None
      else:
        self.points=np.array(self.pointList)
      self.warping=pointLen==4

    def addPoint(self,px,py):
        """ add a point with the given px,py coordinate
        to the warp points make sure we have a maximum of 4 warpPoints if warppoints are complete when adding reset them
        this allows to support click UIs that need an unwarped image before setting new warp points.
        px,py is irrelevant for reset """
        if len(self.pointList)>=4:
          self.pointList=[]
        else:
          self.pointList.append([px,py])
        self.updatePoints()

test_Warp.py

def getTestWarp():
    warp=Warp([])
    warp.addPoint(678,25)
    warp.addPoint(1406,270)
    warp.addPoint(1136,1048)
    warp.addPoint(236,666)
    return warp



def test_WarpPoints():
    warp=getTestWarp()
    print (warp.pointList)
    print (warp.points)
    assert warp.pointList==[[678, 25], [1406, 270], [1136, 1048], [236, 666]]
    # simulate clear click
    warp.addPoint(0,0)
    warp.addPoint(679,25)
    warp.addPoint(1408,270)
    warp.addPoint(1136,1049)
    warp.addPoint(236,667)
    print (warp.pointList)
    print (warp.points)
    assert warp.pointList==[[679, 25], [1408, 270], [1136, 1049], [236, 667]]

test_WarpPoints()
...