Am I code-golfing properly?
There is no 'right' way to golf. You've done well, and the process you've used is fairly standard. Making the program into one statement isn't usually a requirement though.

If it helps, here's how I would approach golfing down your program...

In the hashing function, the for statement can be replaced with a sum:

def h(s):
    r = 0
    r = sum(ord(s[i]) &lt;&lt; (i * len(s)) for i in range(len(s)))
    return r


This can then be defined as a lambda function:

h = lambda s: sum(ord(s[i]) &lt;&lt; (i * len(s)) for i in range(len(s)))


And now we remove unnecessary spaces and brackets:

h=lambda s:sum(ord(s[i])&lt;&lt;i*len(s)for i in range(len(s)))


As Sp3000 pointed out, this can be shortened further with enumerate:

h=lambda s:sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s))


Moving on to the test function, we merge its first two lines:

def test():
    sums = list(map(h, permutations(sample(ascii_lowercase, 9))))
    ...


Since both functions are only used once, we can move everything inline:

sums = list(map(lambda s:sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s)), permutations(sample(ascii_lowercase, 9))))
...


This is shorter as a list comprehension:

sums = [sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s)) for s in permutations(sample(ascii_lowercase, 9))]


Next, we give it a shorter name and remove unnecessary spaces again:

x=[sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))]


The if statement can be moved inside the print function:

print('unique...' if len(set(x)) == len(x) else 'duplicate...')


However, it's usually shorter to use and/or:

print(len(set(x)) == len(x) and 'unique...' or 'duplicate...')


Since len(x) doesn't change, we can calculate and hardcode its value:

print(len(set(x)) == 362880 and 'unique...' or 'duplicate...')


After removing unnecessary spaces and switching around the comparison, we get:

print(len(set(x))&lt;362880and'duplicate...'or'unique...')


This lets us move everything into one statement:

print(len(set([sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))]))&lt;362880and'duplicate...'or'unique...')


And now we can use a set comprehension instead:

print(len({sum(ord(x)&lt;&lt;i*len(s)for i,x in enumerate(s))for s in permutations(sample(ascii_lowercase,9))})&lt;362880and'duplicate...'or'unique...')


The result is 210 bytes, excluding imports. The next step would probably be to golf down the imports or the long strings.