为什么不能在我的代码中自我工作

Why isn't self working in my code

我正在编写一些代码来创建一个在 ArcMap 中编辑地图的工具栏,但我在从我正在使用的其他 classes 中的其他函数获取变量值时遇到了一些问题。

所有函数都是预定义的,所以我不能更改 int 参数,否则代码会抛出错误。我检查了函数中使用 self 定义的变量的 dir() 和 none。我不认为我犯了语法错误,其他 classes 中的代码工作正常。

这是我的代码:

import arcpy
import math
import pythonaddins


class findingCoordinates(object):
    """Implementation for leetScripts_addin.tool (Tool)"""

    def __init__(self):
        self.enabled = True
        self.shape = "NONE"

    def onMouseDownMap(self, x, y, button, shift):
        print "onMouseDowMap executing"
#this is where I declared the first two variables using self
        self.x = x
        self.y = y
        print "Selected point is at %r, %r" % (self.x, self.y)
        pass


class squareFeetInput(object):
    """Implementation for leetScripts_addin.combobox (ComboBox)"""
    def __init__(self):
        self.editable = True
        self.enabled = True
        #self.dropdownWidth = 'WWWWWW'
        self.width = 'WWWWWW'

    def onEditChange(self, text):
        squareFeet = text
#this is the other variable I defined that I need to use later
        self.buffDist = (math.sqrt(float(squareFeet))/2)
        print "Square size: %r ft^2 Buffer Distance: %r ft^2" % (squareFeet,self.buffDist)
        print "self.buffdist is a %r type" % self.buffDist
        return self.buffDist
        pass


class buildingTool(object):
    """Implementation for leetScripts_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        print "building tool is executing"
        #shows im_self, but no x or y
        print "%r" % dir(findingCoordinates.onMouseDownMap)  
        # Get arguments: 
        #   Input point feature class
        #   Output polygon feature class
        #   Buffer distance
        #   Boolean type: Maintain fields and field values of the input in the output 

#This is where the problem is. I can't get these values from the previous functions.

        inPoints   = (findingCoordinates.onMouseDownMap.x,findingCoordinates.onMouseDownMap.y)
        outPolys   = "U:\JackBuildingFootprints.gdb\BuildingFootprintsCopy"
        bufDist    = squareFeetInput.buffDist
        keepFields = true

        # Prepare the output based on whether field and field values are desired in the output
        #
        if keepFields:
            # Create empty output polygon feature class that includes fields of the input
            #
            arcpy.CreateFeatureClass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON",
                                     inPoints, "", "", inPoints)

            # Create a short list of fields to ignore when moving fields values from 
            #  input to output
            #
            ignoreFields = []

            # Use Describe properties to identify the shapeFieldName and OIDFieldName
            #
            desc = arcpy.Describe(inPoints)
            ignoreFields.append(desc.shapeFieldName)
            ignoreFields.append(desc.OIDFieldName)

            # Create a list of fields to use when moving field values from input to output
            #
            fields = arcpy.ListFields(inPoints)
            fieldList = []
            for field in fields:
                if field.name not in ignoreFields:
                    fieldList.append(field.name)
        else:
            # Create empty output polygon feature class without fields of the input
            #
            arcpy.CreateFeatureclass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON",
                                     "", "", "", inPoints)

        # Open searchcursor
        #
        inRows = arcpy.SearchCursor(inPoints)

        # Open insertcursor
        #
        outRows = arcpy.InsertCursor(outPolys)

        # Create point and array objects
        #
        pntObj = arcpy.Point()
        arrayObj = arcpy.Array()

        for inRow in inRows: # One output feature for each input point feature
            inShape = inRow.shape
            pnt = inShape.getPart(0)

            # Need 5 vertices for square buffer: upper right, upper left, lower left,
            #   lower right, upper right. Add and subtract distance from coordinates of
            #   input point as appropriate.
            for vertex in [0,1,2,3,4]:
                pntObj.ID = vertex
                if vertex in [0,3,4]:
                    pntObj.X = pnt.X + bufDist
                else:
                    pntObj.X = pnt.X - bufDist
                if vertex in [0,1,5]:
                    pntObj.Y = pnt.Y + bufDist
                else:
                    pntObj.Y = pnt.Y - bufDist
                arrayObj.add(pntObj)

            # Create new row for output feature
            #
            feat = outRows.newRow()

            # Shift attributes from input to output
            #
            if keepFields == "true":
                for fieldName in fieldList:
                    feat.setValue(fieldName, inRow.getValue(fieldName))

            # Assign array of points to output feature
            #
            feat.shape = arrayObj

            # Insert the feature
            #
            outRows.insertRow(feat)

            # Clear array of points
            #
            arrayObj.removeAll()

        # Delete inputcursor
        #
        del outRows



        pass

我做错了什么?这是我应该使用全局变量的罕见情况之一吗?为什么目录没有显示我使用 self 定义的变量?

编辑:

我不久前做了这个 post,现在我知道的更多了,我只是想澄清一些事情。

第一个:

这是设计用于 python_add_in 的代码。 Python 插件根据您在设置时给它的一些参数创建一个工具栏,以及您放入模板中的任何 python 代码,它都会根据这些参数生成。这实质上意味着上面脚本中的所有 classes 都是在单击或使用工具栏中的按钮和其他工具栏对象时发生的事件。

第二个:

这个问题的解决方案实际上不在公认的答案中,我的错。

问题的根本原因是我使用了我在脚本中声明的 class 名称,例如 findingCoordinates。 python_add_in 不会将这些 class 名称识别为它希望根据您在开始编码之前填写的模板接收的 classes 的名称。

考虑到这一点,问题是我试图调用 class 就 python_add_in 而言根本不存在的 es。解决方案是继续使用 class 名称 python_add_in 工具希望您使用。这些名称位于 class 定义下方的文档字符串中,因此在我有 findingCoordinates 的地方我应该有 Tool.

希望对您有所帮助。

self 指的是您定义的 class 的实例,因此要访问这些值,您需要创建 class 的实例,调用方法,然后访问实例中的值。

例如:

In [9]: %paste
class findingCoordinates(object):
    """Implementation for leetScripts_addin.tool (Tool)"""

    def __init__(self):
        self.enabled = True
        self.shape = "NONE"

    def onMouseDownMap(self, x, y, button, shift):
        print "onMouseDowMap executing"
#this is where I declared the first two variables using self
        self.x = x
        self.y = y
        print "Selected point is at %r, %r" % (self.x, self.y)
        pass

## -- End pasted text --

In [10]: f = findingCoordinates()

In [11]: f.onMouseDownMap(x=1, y=2, button="button", shift="shift")
onMouseDowMap executing
Selected point is at 1, 2

In [12]: f.x
Out[12]: 1

In [13]: f.y
Out[13]: 2

编辑:您似乎也对 scoping/namespaces 感到困惑。没有全局定义 xy;它们只存在于 class 个实例中。这也将允许您为 class.

的不同实例设置单独的 xy
In [14]: x
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-14-401b30e3b8b5> in <module>()
----> 1 x

NameError: name 'x' is not defined

In [15]: y
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-15-009520053b00> in <module>()
----> 1 y

NameError: name 'y' is not defined

In [16]: g = findingCoordinates()

In [17]: g.onMouseDownMap(100,200,0,0)
onMouseDowMap executing
Selected point is at 100, 200

In [18]: f.x, f.y
Out[18]: (1, 2)

In [19]: g.x, g.y
Out[19]: (100, 200)